LCOV - code coverage report
Current view: top level - vcl/source/window - menu.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 995 1710 58.2 %
Date: 2015-06-13 12:38:46 Functions: 94 152 61.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/debug.hxx>
      21             : #include <tools/diagnose_ex.h>
      22             : #include <tools/rc.h>
      23             : #include <tools/stream.hxx>
      24             : 
      25             : #include <vcl/svapp.hxx>
      26             : #include <vcl/mnemonic.hxx>
      27             : #include <vcl/image.hxx>
      28             : #include <vcl/event.hxx>
      29             : #include <vcl/help.hxx>
      30             : #include <vcl/floatwin.hxx>
      31             : #include <vcl/wrkwin.hxx>
      32             : #include <vcl/timer.hxx>
      33             : #include <vcl/decoview.hxx>
      34             : #include <vcl/bitmap.hxx>
      35             : #include <vcl/menu.hxx>
      36             : #include <vcl/button.hxx>
      37             : #include <vcl/gradient.hxx>
      38             : #include <vcl/i18nhelp.hxx>
      39             : #include <vcl/taskpanelist.hxx>
      40             : #include <vcl/controllayout.hxx>
      41             : #include <vcl/toolbox.hxx>
      42             : #include <vcl/dockingarea.hxx>
      43             : #include <vcl/settings.hxx>
      44             : 
      45             : #include <salinst.hxx>
      46             : #include <svdata.hxx>
      47             : #include <svids.hrc>
      48             : #include <window.h>
      49             : #include <salmenu.hxx>
      50             : #include <salframe.hxx>
      51             : 
      52             : #include "menubarwindow.hxx"
      53             : #include "menufloatingwindow.hxx"
      54             : #include "menuitemlist.hxx"
      55             : 
      56             : #include <com/sun/star/uno/Reference.h>
      57             : #include <com/sun/star/lang/XComponent.hpp>
      58             : #include <com/sun/star/accessibility/XAccessible.hpp>
      59             : #include <com/sun/star/accessibility/AccessibleRole.hpp>
      60             : #include <vcl/unowrap.hxx>
      61             : 
      62             : #include <vcl/unohelp.hxx>
      63             : #include <vcl/configsettings.hxx>
      64             : 
      65             : #include "vcl/lazydelete.hxx"
      66             : 
      67             : #include <sfx2/sfxsids.hrc>
      68             : 
      69             : #include <map>
      70             : #include <vector>
      71             : 
      72             : namespace vcl
      73             : {
      74             : 
      75           4 : struct MenuLayoutData : public ControlLayoutData
      76             : {
      77             :     std::vector< sal_uInt16 >               m_aLineItemIds;
      78             :     std::vector< sal_uInt16 >               m_aLineItemPositions;
      79             :     std::map< sal_uInt16, Rectangle >       m_aVisibleItemBoundRects;
      80             : };
      81             : 
      82             : }
      83             : 
      84             : using namespace ::com::sun::star;
      85             : using namespace vcl;
      86             : 
      87             : #define EXTRAITEMHEIGHT     4
      88             : #define SPACE_AROUND_TITLE  2
      89             : 
      90           0 : static bool ImplAccelDisabled()
      91             : {
      92             :     // display of accelerator strings may be suppressed via configuration
      93             :     static int nAccelDisabled = -1;
      94             : 
      95           0 :     if( nAccelDisabled == -1 )
      96             :     {
      97             :         OUString aStr =
      98             :             vcl::SettingsConfigItem::get()->
      99           0 :             getValue( "Menu", "SuppressAccelerators" );
     100           0 :         nAccelDisabled = aStr.equalsIgnoreAsciiCase("true") ? 1 : 0;
     101             :     }
     102           0 :     return nAccelDisabled == 1;
     103             : }
     104             : 
     105       27535 : static void ImplSetMenuItemData( MenuItemData* pData )
     106             : {
     107             :     // convert data
     108       27535 :     if ( !pData->aImage )
     109        5643 :         pData->eType = MenuItemType::STRING;
     110       21892 :     else if ( pData->aText.isEmpty() )
     111          37 :         pData->eType = MenuItemType::IMAGE;
     112             :     else
     113       21855 :         pData->eType = MenuItemType::STRINGIMAGE;
     114       27535 : }
     115             : 
     116       77988 : Menu::Menu()
     117             :     : mpFirstDel(NULL),
     118       77988 :       pItemList(new MenuItemList),
     119             :       pLogo(NULL),
     120             :       pStartedFrom(NULL),
     121             :       pWindow(NULL),
     122             :       nTitleHeight(0),
     123             :       nEventId(0),
     124             :       mnHighlightedItemPos(ITEMPOS_INVALID),
     125             :       nMenuFlags(MenuFlags::NONE),
     126             :       nDefaultItem(0),
     127             :       nSelectedId(0),
     128             :       nImgOrChkPos(0),
     129             :       nTextPos(0),
     130             :       bCanceled(false),
     131             :       bInCallback(false),
     132             :       bKilled(false),
     133             :       mpLayoutData(NULL),
     134      155976 :       mpSalMenu(NULL)
     135             : {
     136       77988 : }
     137             : 
     138      155912 : Menu::~Menu()
     139             : {
     140       77956 :     ImplCallEventListeners( VCLEVENT_OBJECT_DYING, ITEMPOS_INVALID );
     141             : 
     142             :     // at the window free the reference to the accessible component
     143             :     // and make sure the MenuFloatingWindow knows about our destruction
     144       77956 :     if ( pWindow )
     145             :     {
     146           0 :         MenuFloatingWindow* pFloat = static_cast<MenuFloatingWindow*>(pWindow.get());
     147           0 :         if( pFloat->pMenu == this )
     148           0 :             pFloat->pMenu = NULL;
     149           0 :         pWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
     150             :     }
     151             : 
     152             :     // dispose accessible components
     153       77956 :     if ( mxAccessible.is() )
     154             :     {
     155         350 :         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComponent( mxAccessible, ::com::sun::star::uno::UNO_QUERY );
     156         350 :         if ( xComponent.is() )
     157         350 :             xComponent->dispose();
     158             :     }
     159             : 
     160       77956 :     if ( nEventId )
     161           0 :         Application::RemoveUserEvent( nEventId );
     162             : 
     163             :     // Notify deletion of this menu
     164       77956 :     ImplMenuDelData* pDelData = mpFirstDel;
     165      155912 :     while ( pDelData )
     166             :     {
     167           0 :         pDelData->mpMenu = NULL;
     168           0 :         pDelData = pDelData->mpNext;
     169             :     }
     170             : 
     171       77956 :     bKilled = true;
     172             : 
     173       77956 :     delete pItemList;
     174       77956 :     delete pLogo;
     175       77956 :     delete mpLayoutData;
     176             : 
     177             :     // Native-support: destroy SalMenu
     178       77956 :     ImplSetSalMenu( NULL );
     179       77956 : }
     180             : 
     181           9 : void Menu::CreateAutoMnemonics()
     182             : {
     183           9 :     MnemonicGenerator aMnemonicGenerator;
     184             :     size_t n;
     185         247 :     for ( n = 0; n < pItemList->size(); n++ )
     186             :     {
     187         238 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
     188         238 :         if ( ! (pData->nBits & MenuItemBits::NOSELECT ) )
     189         238 :             aMnemonicGenerator.RegisterMnemonic( pData->aText );
     190             :     }
     191         247 :     for ( n = 0; n < pItemList->size(); n++ )
     192             :     {
     193         238 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
     194         238 :         if ( ! (pData->nBits & MenuItemBits::NOSELECT ) )
     195         238 :             pData->aText = aMnemonicGenerator.CreateMnemonic( pData->aText );
     196           9 :     }
     197           9 : }
     198             : 
     199          18 : void Menu::Activate()
     200             : {
     201          18 :     bInCallback = true;
     202             : 
     203          18 :     ImplMenuDelData aDelData( this );
     204             : 
     205          18 :     ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE, ITEMPOS_INVALID );
     206             : 
     207          18 :     if( !aDelData.isDeleted() )
     208             :     {
     209          18 :         if ( !aActivateHdl.Call( this ) )
     210             :         {
     211           0 :             if( !aDelData.isDeleted() )
     212             :             {
     213           0 :                 Menu* pStartMenu = ImplGetStartMenu();
     214           0 :                 if ( pStartMenu && ( pStartMenu != this ) )
     215             :                 {
     216           0 :                     pStartMenu->bInCallback = true;
     217             :                     // MT 11/01: Call EventListener here? I don't know...
     218           0 :                     pStartMenu->aActivateHdl.Call( this );
     219           0 :                     pStartMenu->bInCallback = false;
     220             :                 }
     221             :             }
     222             :         }
     223          18 :         bInCallback = false;
     224          18 :     }
     225          18 : }
     226             : 
     227          24 : void Menu::Deactivate()
     228             : {
     229         421 :     for ( size_t n = pItemList->size(); n; )
     230             :     {
     231         373 :         MenuItemData* pData = pItemList->GetDataFromPos( --n );
     232         373 :         if ( pData->bIsTemporary )
     233           0 :             pItemList->Remove( n );
     234             :     }
     235             : 
     236          24 :     bInCallback = true;
     237             : 
     238          24 :     ImplMenuDelData aDelData( this );
     239             : 
     240          24 :     Menu* pStartMenu = ImplGetStartMenu();
     241          24 :     ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE, ITEMPOS_INVALID );
     242             : 
     243          24 :     if( !aDelData.isDeleted() )
     244             :     {
     245          24 :         if ( !aDeactivateHdl.Call( this ) )
     246             :         {
     247           0 :             if( !aDelData.isDeleted() )
     248             :             {
     249           0 :                 if ( pStartMenu && ( pStartMenu != this ) )
     250             :                 {
     251           0 :                     pStartMenu->bInCallback = true;
     252           0 :                     pStartMenu->aDeactivateHdl.Call( this );
     253           0 :                     pStartMenu->bInCallback = false;
     254             :                 }
     255             :             }
     256             :         }
     257             :     }
     258             : 
     259          24 :     if( !aDelData.isDeleted() )
     260             :     {
     261          24 :         bInCallback = false;
     262          24 :     }
     263          24 : }
     264             : 
     265          26 : void Menu::Highlight()
     266             : {
     267          26 :     ImplMenuDelData aDelData( this );
     268             : 
     269          26 :     Menu* pStartMenu = ImplGetStartMenu();
     270          26 :     if ( !aHighlightHdl.Call( this ) && !aDelData.isDeleted() )
     271             :     {
     272          26 :         if ( pStartMenu && ( pStartMenu != this ) )
     273           0 :             pStartMenu->aHighlightHdl.Call( this );
     274          26 :     }
     275          26 : }
     276             : 
     277           0 : void Menu::ImplSelect()
     278             : {
     279           0 :     MenuItemData* pData = GetItemList()->GetData( nSelectedId );
     280           0 :     if ( pData && (pData->nBits & MenuItemBits::AUTOCHECK) )
     281             :     {
     282           0 :         bool bChecked = IsItemChecked( nSelectedId );
     283           0 :         if ( pData->nBits & MenuItemBits::RADIOCHECK )
     284             :         {
     285           0 :             if ( !bChecked )
     286           0 :                 CheckItem( nSelectedId, true );
     287             :         }
     288             :         else
     289           0 :             CheckItem( nSelectedId, !bChecked );
     290             :     }
     291             : 
     292             :     // call select
     293           0 :     ImplSVData* pSVData = ImplGetSVData();
     294           0 :     pSVData->maAppData.mpActivePopupMenu = NULL;        // if new execute in select()
     295           0 :     nEventId = Application::PostUserEvent( LINK( this, Menu, ImplCallSelect ) );
     296           0 : }
     297             : 
     298           0 : void Menu::Select()
     299             : {
     300           0 :     ImplMenuDelData aDelData( this );
     301             : 
     302           0 :     ImplCallEventListeners( VCLEVENT_MENU_SELECT, GetItemPos( GetCurItemId() ) );
     303           0 :     if ( !aDelData.isDeleted() && !aSelectHdl.Call( this ) )
     304             :     {
     305           0 :         if( !aDelData.isDeleted() )
     306             :         {
     307           0 :             Menu* pStartMenu = ImplGetStartMenu();
     308           0 :             if ( pStartMenu && ( pStartMenu != this ) )
     309             :             {
     310           0 :                 pStartMenu->nSelectedId = nSelectedId;
     311           0 :                 pStartMenu->aSelectHdl.Call( this );
     312             :             }
     313             :         }
     314           0 :     }
     315           0 : }
     316             : 
     317             : #if defined(MACOSX)
     318             : void Menu::ImplSelectWithStart( Menu* pSMenu )
     319             : {
     320             :     Menu* pOldStartedFrom = pStartedFrom;
     321             :     pStartedFrom = pSMenu;
     322             :     Menu* pOldStartedStarted = pOldStartedFrom ? pOldStartedFrom->pStartedFrom : NULL;
     323             :     Select();
     324             :     if( pOldStartedFrom )
     325             :         pOldStartedFrom->pStartedFrom = pOldStartedStarted;
     326             :     pStartedFrom = pOldStartedFrom;
     327             : }
     328             : #endif
     329             : 
     330      427538 : void Menu::ImplCallEventListeners( sal_uLong nEvent, sal_uInt16 nPos )
     331             : {
     332      427538 :     ImplMenuDelData aDelData( this );
     333             : 
     334      855076 :     VclMenuEvent aEvent( this, nEvent, nPos );
     335             : 
     336             :     // This is needed by atk accessibility bridge
     337      427538 :     if ( nEvent == VCLEVENT_MENU_HIGHLIGHT )
     338             :     {
     339          26 :         Application::ImplCallEventListeners( &aEvent );
     340             :     }
     341             : 
     342      427538 :     if ( !aDelData.isDeleted() )
     343      427538 :         maEventListeners.Call( &aEvent );
     344             : 
     345      427538 :     if( !aDelData.isDeleted() )
     346             :     {
     347      427538 :         Menu* pMenu = this;
     348     1282770 :         while ( pMenu )
     349             :         {
     350      427694 :             maChildEventListeners.Call( &aEvent );
     351             : 
     352      427694 :             if( aDelData.isDeleted() )
     353           0 :                 break;
     354             : 
     355      427694 :             pMenu = ( pMenu->pStartedFrom != pMenu ) ? pMenu->pStartedFrom : NULL;
     356             :         }
     357      427538 :     }
     358      427538 : }
     359             : 
     360        6338 : void Menu::AddEventListener( const Link<>& rEventListener )
     361             : {
     362        6338 :     maEventListeners.addListener( rEventListener );
     363        6338 : }
     364             : 
     365        9529 : void Menu::RemoveEventListener( const Link<>& rEventListener )
     366             : {
     367        9529 :     maEventListeners.removeListener( rEventListener );
     368        9529 : }
     369             : 
     370      246802 : MenuItemData* Menu::NbcInsertItem(sal_uInt16 nId, MenuItemBits nBits,
     371             :                                   const OUString& rStr, Menu* pMenu,
     372             :                                   size_t nPos, const OString &rIdent)
     373             : {
     374             :     // put Item in MenuItemList
     375             :     MenuItemData* pData = pItemList->Insert(nId, MenuItemType::STRING,
     376      246802 :                              nBits, rStr, Image(), pMenu, nPos, rIdent);
     377             : 
     378             :     // update native menu
     379      246802 :     if (ImplGetSalMenu() && pData->pSalMenuItem)
     380         113 :         ImplGetSalMenu()->InsertItem(pData->pSalMenuItem, nPos);
     381             : 
     382      246802 :     return pData;
     383             : }
     384             : 
     385      246802 : void Menu::InsertItem(sal_uInt16 nItemId, const OUString& rStr, MenuItemBits nItemBits,
     386             :     const OString &rIdent, sal_uInt16 nPos)
     387             : {
     388             :     DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
     389             :     DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
     390             :                 "Menu::InsertItem(): ItemId already exists" );
     391             : 
     392             :     // if Position > ItemCount, append
     393      246802 :     if ( nPos >= pItemList->size() )
     394      246801 :         nPos = MENU_APPEND;
     395             : 
     396             :     // put Item in MenuItemList
     397      246802 :     NbcInsertItem(nItemId, nItemBits, rStr, this, nPos, rIdent);
     398             : 
     399      246802 :     vcl::Window* pWin = ImplGetWindow();
     400      246802 :     delete mpLayoutData, mpLayoutData = NULL;
     401      246802 :     if ( pWin )
     402             :     {
     403          57 :         ImplCalcSize( pWin );
     404          57 :         if ( pWin->IsVisible() )
     405          57 :             pWin->Invalidate();
     406             :     }
     407      246802 :     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
     408      246802 : }
     409             : 
     410           0 : void Menu::InsertItem(sal_uInt16 nItemId, const Image& rImage,
     411             :     MenuItemBits nItemBits, const OString &rIdent, sal_uInt16 nPos)
     412             : {
     413           0 :     InsertItem(nItemId, OUString(), nItemBits, rIdent, nPos);
     414           0 :     SetItemImage( nItemId, rImage );
     415           0 : }
     416             : 
     417       14544 : void Menu::InsertItem(sal_uInt16 nItemId, const OUString& rStr,
     418             :     const Image& rImage, MenuItemBits nItemBits,
     419             :     const OString &rIdent, sal_uInt16 nPos)
     420             : {
     421       14544 :     InsertItem(nItemId, rStr, nItemBits, rIdent, nPos);
     422       14544 :     SetItemImage( nItemId, rImage );
     423       14544 : }
     424             : 
     425        5246 : void Menu::InsertItem( const ResId& rResId, sal_uInt16 nPos )
     426             : {
     427        5246 :     ResMgr* pMgr = rResId.GetResMgr();
     428        5246 :     if( ! pMgr )
     429        5246 :         return;
     430             : 
     431             :     sal_uLong              nObjMask;
     432             : 
     433        5246 :     GetRes( rResId.SetRT( RSC_MENUITEM ) );
     434        5246 :     nObjMask    = ReadLongRes();
     435             : 
     436        5246 :     bool bSep = false;
     437        5246 :     if ( nObjMask & RSC_MENUITEM_SEPARATOR )
     438          86 :         bSep = ReadShortRes() != 0;
     439             : 
     440        5246 :     sal_uInt16 nItemId = 1;
     441        5246 :     if ( nObjMask & RSC_MENUITEM_ID )
     442        4365 :         nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
     443             : 
     444        5246 :     MenuItemBits nStatus = MenuItemBits::NONE;
     445        5246 :     if ( nObjMask & RSC_MENUITEM_STATUS )
     446        3201 :         nStatus = sal::static_int_cast<MenuItemBits>(ReadLongRes());
     447             : 
     448        5246 :     OUString aText;
     449        5246 :     if ( nObjMask & RSC_MENUITEM_TEXT )
     450        5160 :         aText = ReadStringRes();
     451             : 
     452             :     // create item
     453        5246 :     if ( nObjMask & RSC_MENUITEM_BITMAP )
     454             :     {
     455           0 :         if ( !bSep )
     456             :         {
     457           0 :             Bitmap aBmp( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *pMgr ) );
     458           0 :             Image const aImg(aBmp);
     459           0 :             if ( !aText.isEmpty() )
     460           0 :                 InsertItem( nItemId, aText, aImg, nStatus, OString(), nPos );
     461             :             else
     462           0 :                 InsertItem( nItemId, aImg, nStatus, OString(), nPos );
     463             :         }
     464           0 :         IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
     465             :     }
     466        5246 :     else if ( !bSep )
     467        5160 :         InsertItem(nItemId, aText, nStatus, OString(), nPos);
     468        5246 :     if ( bSep )
     469          86 :         InsertSeparator(OString(), nPos);
     470             : 
     471       10492 :     OUString aHelpText;
     472        5246 :     if ( nObjMask & RSC_MENUITEM_HELPTEXT )
     473             :     {
     474           0 :         aHelpText = ReadStringRes();
     475           0 :         if( !bSep )
     476           0 :             SetHelpText( nItemId, aHelpText );
     477             :     }
     478             : 
     479        5246 :     if ( nObjMask & RSC_MENUITEM_HELPID )
     480             :     {
     481         963 :         OString aHelpId( ReadByteStringRes() );
     482         963 :         if ( !bSep )
     483         963 :             SetHelpId( nItemId, aHelpId );
     484             :     }
     485             : 
     486        5246 :     if( !bSep )
     487        5160 :         SetHelpText( nItemId, aHelpText );
     488             : 
     489        5246 :     if ( nObjMask & RSC_MENUITEM_KEYCODE )
     490             :     {
     491           0 :         if ( !bSep )
     492           0 :             SetAccelKey( nItemId, KeyCode( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *pMgr ) ) );
     493           0 :         IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
     494             :     }
     495        5246 :     if( nObjMask & RSC_MENUITEM_CHECKED )
     496             :     {
     497           0 :         if ( !bSep )
     498           0 :             CheckItem( nItemId, ReadShortRes() != 0 );
     499             :     }
     500        5246 :     if ( nObjMask & RSC_MENUITEM_DISABLE )
     501             :     {
     502           0 :         if ( !bSep )
     503           0 :             EnableItem( nItemId, ReadShortRes() == 0 );
     504             :     }
     505        5246 :     if ( nObjMask & RSC_MENUITEM_COMMAND )
     506             :     {
     507          21 :         OUString aCommandStr = ReadStringRes();
     508          21 :         if ( !bSep )
     509          21 :             SetItemCommand( nItemId, aCommandStr );
     510             :     }
     511        5246 :     if ( nObjMask & RSC_MENUITEM_MENU )
     512             :     {
     513           4 :         if ( !bSep )
     514             :         {
     515           4 :             MenuItemData* pData = GetItemList()->GetData( nItemId );
     516           4 :             if ( pData )
     517             :             {
     518           4 :                 PopupMenu* pSubMenu = new PopupMenu( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *pMgr ) );
     519           4 :                 pData->pAutoSubMenu = pSubMenu;
     520             :                 // #111060# keep track of this pointer, may be it will be deleted from outside
     521           4 :                 pSubMenu->pRefAutoSubMenu = &pData->pAutoSubMenu;
     522           4 :                 SetPopupMenu( nItemId, pSubMenu );
     523             :             }
     524             :         }
     525           4 :         IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
     526             :     }
     527       10492 :     delete mpLayoutData, mpLayoutData = NULL;
     528             : }
     529             : 
     530       46810 : void Menu::InsertSeparator(const OString &rIdent, sal_uInt16 nPos)
     531             : {
     532             :     // do nothing if it's a menu bar
     533       46810 :     if (IsMenuBar())
     534       46810 :         return;
     535             : 
     536             :     // if position > ItemCount, append
     537       46810 :     if ( nPos >= pItemList->size() )
     538       46810 :         nPos = MENU_APPEND;
     539             : 
     540             :     // put separator in item list
     541       46810 :     pItemList->InsertSeparator(rIdent, nPos);
     542             : 
     543             :     // update native menu
     544       46810 :     size_t itemPos = ( nPos != MENU_APPEND ) ? nPos : pItemList->size() - 1;
     545       46810 :     MenuItemData *pData = pItemList->GetDataFromPos( itemPos );
     546       46810 :     if( ImplGetSalMenu() && pData && pData->pSalMenuItem )
     547          23 :         ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
     548             : 
     549       46810 :     delete mpLayoutData, mpLayoutData = NULL;
     550             : 
     551       46810 :     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
     552             : }
     553             : 
     554          61 : void Menu::RemoveItem( sal_uInt16 nPos )
     555             : {
     556          61 :     bool bRemove = false;
     557             : 
     558          61 :     if ( nPos < GetItemCount() )
     559             :     {
     560             :         // update native menu
     561          61 :         if( ImplGetSalMenu() )
     562           0 :             ImplGetSalMenu()->RemoveItem( nPos );
     563             : 
     564          61 :         pItemList->Remove( nPos );
     565          61 :         bRemove = true;
     566             :     }
     567             : 
     568          61 :     vcl::Window* pWin = ImplGetWindow();
     569          61 :     if ( pWin )
     570             :     {
     571          57 :         ImplCalcSize( pWin );
     572          57 :         if ( pWin->IsVisible() )
     573          57 :             pWin->Invalidate();
     574             :     }
     575          61 :     delete mpLayoutData, mpLayoutData = NULL;
     576             : 
     577          61 :     if ( bRemove )
     578          61 :         ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM, nPos );
     579          61 : }
     580             : 
     581        9090 : void ImplCopyItem( Menu* pThis, const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos,
     582             :                   sal_uInt16 nMode = 0 )
     583             : {
     584        9090 :     MenuItemType eType = rMenu.GetItemType( nPos );
     585             : 
     586        9090 :     if ( eType == MenuItemType::DONTKNOW )
     587           0 :         return;
     588             : 
     589        9090 :     if ( eType == MenuItemType::SEPARATOR )
     590        1818 :         pThis->InsertSeparator( OString(), nNewPos );
     591             :     else
     592             :     {
     593        7272 :         sal_uInt16 nId = rMenu.GetItemId( nPos );
     594             : 
     595             :         DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
     596             :                     "Menu::CopyItem(): ItemId already exists" );
     597             : 
     598        7272 :         MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
     599             : 
     600        7272 :         if (!pData)
     601           0 :             return;
     602             : 
     603        7272 :         if ( eType == MenuItemType::STRINGIMAGE )
     604        7272 :             pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, pData->sIdent, nNewPos );
     605           0 :         else if ( eType == MenuItemType::STRING )
     606           0 :             pThis->InsertItem( nId, pData->aText, pData->nBits, pData->sIdent, nNewPos );
     607             :         else
     608           0 :             pThis->InsertItem( nId, pData->aImage, pData->nBits, pData->sIdent, nNewPos );
     609             : 
     610        7272 :         if ( rMenu.IsItemChecked( nId ) )
     611           0 :             pThis->CheckItem( nId, true );
     612        7272 :         if ( !rMenu.IsItemEnabled( nId ) )
     613           0 :             pThis->EnableItem( nId, false );
     614        7272 :         pThis->SetHelpId( nId, pData->aHelpId );
     615        7272 :         pThis->SetHelpText( nId, pData->aHelpText );
     616        7272 :         pThis->SetAccelKey( nId, pData->aAccelKey );
     617        7272 :         pThis->SetItemCommand( nId, pData->aCommandStr );
     618        7272 :         pThis->SetHelpCommand( nId, pData->aHelpCommandStr );
     619             : 
     620        7272 :         PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
     621        7272 :         if ( pSubMenu )
     622             :         {
     623             :             // create auto-copy
     624           0 :             if ( nMode == 1 )
     625             :             {
     626           0 :                 PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
     627           0 :                 pThis->SetPopupMenu( nId, pNewMenu );
     628             :             }
     629             :             else
     630           0 :                 pThis->SetPopupMenu( nId, pSubMenu );
     631             :         }
     632             :     }
     633             : }
     634             : 
     635           0 : void Menu::CopyItem( const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos )
     636             : {
     637           0 :     ImplCopyItem( this, rMenu, nPos, nNewPos );
     638           0 : }
     639             : 
     640         613 : void Menu::Clear()
     641             : {
     642         670 :     for ( sal_uInt16 i = GetItemCount(); i; i-- )
     643          57 :         RemoveItem( 0 );
     644         613 : }
     645             : 
     646      121973 : sal_uInt16 Menu::GetItemCount() const
     647             : {
     648      121973 :     return (sal_uInt16)pItemList->size();
     649             : }
     650             : 
     651           8 : sal_uInt16 Menu::ImplGetVisibleItemCount() const
     652             : {
     653           8 :     sal_uInt16 nItems = 0;
     654         245 :     for ( size_t n = pItemList->size(); n; )
     655             :     {
     656         229 :         if ( ImplIsVisible( --n ) )
     657         229 :             nItems++;
     658             :     }
     659           8 :     return nItems;
     660             : }
     661             : 
     662           0 : sal_uInt16 Menu::ImplGetFirstVisible() const
     663             : {
     664           0 :     for ( size_t n = 0; n < pItemList->size(); n++ )
     665             :     {
     666           0 :         if ( ImplIsVisible( n ) )
     667           0 :             return n;
     668             :     }
     669           0 :     return ITEMPOS_INVALID;
     670             : }
     671             : 
     672           0 : sal_uInt16 Menu::ImplGetPrevVisible( sal_uInt16 nPos ) const
     673             : {
     674           0 :     for ( size_t n = nPos; n; )
     675             :     {
     676           0 :         if ( n && ImplIsVisible( --n ) )
     677           0 :             return n;
     678             :     }
     679           0 :     return ITEMPOS_INVALID;
     680             : }
     681             : 
     682           0 : sal_uInt16 Menu::ImplGetNextVisible( sal_uInt16 nPos ) const
     683             : {
     684           0 :     for ( size_t n = nPos+1; n < pItemList->size(); n++ )
     685             :     {
     686           0 :         if ( ImplIsVisible( n ) )
     687           0 :             return n;
     688             :     }
     689           0 :     return ITEMPOS_INVALID;
     690             : }
     691             : 
     692      343160 : sal_uInt16 Menu::GetItemId(sal_uInt16 nPos) const
     693             : {
     694      343160 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
     695             : 
     696      343160 :     if ( pData )
     697      343160 :         return pData->nId;
     698             :     else
     699           0 :         return 0;
     700             : }
     701             : 
     702           0 : sal_uInt16 Menu::GetItemId(const OString &rIdent) const
     703             : {
     704           0 :     for (size_t n = 0; n < pItemList->size(); ++n)
     705             :     {
     706           0 :         MenuItemData* pData = pItemList->GetDataFromPos(n);
     707           0 :         if (pData && pData->sIdent == rIdent)
     708           0 :             return pData->nId;
     709             :     }
     710           0 :     return MENU_ITEM_NOTFOUND;
     711             : }
     712             : 
     713        1615 : sal_uInt16 Menu::GetItemPos( sal_uInt16 nItemId ) const
     714             : {
     715             :     size_t          nPos;
     716        1615 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     717             : 
     718        1615 :     if ( pData )
     719        1599 :         return (sal_uInt16)nPos;
     720             :     else
     721          16 :         return MENU_ITEM_NOTFOUND;
     722             : }
     723             : 
     724      269994 : MenuItemType Menu::GetItemType( sal_uInt16 nPos ) const
     725             : {
     726      269994 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
     727             : 
     728      269994 :     if ( pData )
     729      262722 :         return pData->eType;
     730             :     else
     731        7272 :         return MenuItemType::DONTKNOW;
     732             : }
     733             : 
     734           0 : OString Menu::GetCurItemIdent() const
     735             : {
     736           0 :     const MenuItemData* pData = pItemList->GetData(nSelectedId);
     737           0 :     return pData ? pData->sIdent : OString();
     738             : }
     739             : 
     740           0 : OString Menu::GetItemIdent(sal_uInt16 nId) const
     741             : {
     742           0 :     const MenuItemData* pData = pItemList->GetData(nId);
     743           0 :     return pData ? pData->sIdent : OString();
     744             : }
     745             : 
     746        8392 : void Menu::SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits )
     747             : {
     748        8392 :     MenuItemData* pData = pItemList->GetData( nItemId );
     749        8392 :     if ( pData )
     750        8392 :         pData->nBits = nBits;
     751        8392 : }
     752             : 
     753       10530 : MenuItemBits Menu::GetItemBits( sal_uInt16 nItemId ) const
     754             : {
     755       10530 :     MenuItemBits nBits = MenuItemBits::NONE;
     756       10530 :     MenuItemData* pData = pItemList->GetData( nItemId );
     757       10530 :     if ( pData )
     758       10530 :         nBits = pData->nBits;
     759       10530 :     return nBits;
     760             : }
     761             : 
     762       14584 : void Menu::SetUserValue(sal_uInt16 nItemId, sal_uLong nValue, MenuUserDataReleaseFunction aFunc)
     763             : {
     764       14584 :     MenuItemData* pData = pItemList->GetData(nItemId);
     765       14584 :     if (pData)
     766             :     {
     767       14584 :         if (pData->aUserValueReleaseFunc)
     768           0 :             pData->aUserValueReleaseFunc(pData->nUserValue);
     769       14584 :         pData->aUserValueReleaseFunc = aFunc;
     770       14584 :         pData->nUserValue = nValue;
     771             :     }
     772       14584 : }
     773             : 
     774       43163 : sal_uLong Menu::GetUserValue( sal_uInt16 nItemId ) const
     775             : {
     776       43163 :     MenuItemData* pData = pItemList->GetData( nItemId );
     777       43163 :     return pData ? pData->nUserValue : 0;
     778             : }
     779             : 
     780       39910 : void Menu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu )
     781             : {
     782             :     size_t          nPos;
     783       39910 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     784             : 
     785             :     // Item does not exist -> return NULL
     786       39910 :     if ( !pData )
     787           0 :         return;
     788             : 
     789             :     // same menu, nothing to do
     790       39910 :     if ( static_cast<PopupMenu*>(pData->pSubMenu) == pMenu )
     791           0 :         return;
     792             : 
     793             :     // data exchange
     794       39910 :     pData->pSubMenu = pMenu;
     795             : 
     796             :     // #112023# Make sure pStartedFrom does not point to invalid (old) data
     797       39910 :     if ( pData->pSubMenu )
     798       34530 :         pData->pSubMenu->pStartedFrom = 0;
     799             : 
     800             :     // set native submenu
     801       39910 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
     802             :     {
     803          24 :         if( pMenu )
     804          19 :             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, pMenu->ImplGetSalMenu(), nPos );
     805             :         else
     806           5 :             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, NULL, nPos );
     807             :     }
     808             : 
     809       39910 :     ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED, nPos );
     810             : }
     811             : 
     812      309899 : PopupMenu* Menu::GetPopupMenu( sal_uInt16 nItemId ) const
     813             : {
     814      309899 :     MenuItemData* pData = pItemList->GetData( nItemId );
     815             : 
     816      309899 :     if ( pData )
     817      297185 :         return static_cast<PopupMenu*>(pData->pSubMenu);
     818             :     else
     819       12714 :         return NULL;
     820             : }
     821             : 
     822        7421 : void Menu::SetAccelKey( sal_uInt16 nItemId, const KeyCode& rKeyCode )
     823             : {
     824             :     size_t          nPos;
     825        7421 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     826             : 
     827        7421 :     if ( !pData )
     828        7421 :         return;
     829             : 
     830        7421 :     if ( pData->aAccelKey == rKeyCode )
     831        7421 :         return;
     832             : 
     833           0 :     pData->aAccelKey = rKeyCode;
     834             : 
     835             :     // update native menu
     836           0 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
     837           0 :         ImplGetSalMenu()->SetAccelerator( nPos, pData->pSalMenuItem, rKeyCode, rKeyCode.GetName() );
     838             : }
     839             : 
     840           1 : KeyCode Menu::GetAccelKey( sal_uInt16 nItemId ) const
     841             : {
     842           1 :     MenuItemData* pData = pItemList->GetData( nItemId );
     843             : 
     844           1 :     if ( pData )
     845           1 :         return pData->aAccelKey;
     846             :     else
     847           0 :         return KeyCode();
     848             : }
     849             : 
     850           1 : KeyEvent Menu::GetActivationKey( sal_uInt16 nItemId ) const
     851             : {
     852           1 :     KeyEvent aRet;
     853           1 :     MenuItemData* pData = pItemList->GetData( nItemId );
     854           1 :     if( pData )
     855             :     {
     856           1 :         sal_Int32 nPos = pData->aText.indexOf( '~' );
     857           1 :         if( nPos != -1 && nPos < pData->aText.getLength()-1 )
     858             :         {
     859           1 :             sal_uInt16 nCode = 0;
     860           1 :             sal_Unicode cAccel = pData->aText[nPos+1];
     861           1 :             if( cAccel >= 'a' && cAccel <= 'z' )
     862           0 :                 nCode = KEY_A + (cAccel-'a');
     863           1 :             else if( cAccel >= 'A' && cAccel <= 'Z' )
     864           1 :                 nCode = KEY_A + (cAccel-'A');
     865           0 :             else if( cAccel >= '0' && cAccel <= '9' )
     866           0 :                 nCode = KEY_0 + (cAccel-'0');
     867           1 :             if(nCode )
     868           1 :                 aRet = KeyEvent( cAccel, KeyCode( nCode, KEY_MOD2 ) );
     869             :         }
     870             : 
     871             :     }
     872           1 :     return aRet;
     873             : }
     874             : 
     875         898 : void Menu::CheckItem( sal_uInt16 nItemId, bool bCheck )
     876             : {
     877             :     size_t          nPos;
     878         898 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     879             : 
     880         898 :     if ( !pData || pData->bChecked == bCheck )
     881         985 :         return;
     882             : 
     883             :     // if radio-check, then uncheck previous
     884        1628 :     if ( bCheck && (pData->nBits & MenuItemBits::AUTOCHECK) &&
     885         817 :          (pData->nBits & MenuItemBits::RADIOCHECK) )
     886             :     {
     887             :         MenuItemData*   pGroupData;
     888             :         sal_uInt16          nGroupPos;
     889           3 :         sal_uInt16          nItemCount = GetItemCount();
     890           3 :         bool            bFound = false;
     891             : 
     892           3 :         nGroupPos = nPos;
     893           6 :         while ( nGroupPos )
     894             :         {
     895           0 :             pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
     896           0 :             if ( pGroupData->nBits & MenuItemBits::RADIOCHECK )
     897             :             {
     898           0 :                 if ( IsItemChecked( pGroupData->nId ) )
     899             :                 {
     900           0 :                     CheckItem( pGroupData->nId, false );
     901           0 :                     bFound = true;
     902           0 :                     break;
     903             :                 }
     904             :             }
     905             :             else
     906           0 :                 break;
     907           0 :             nGroupPos--;
     908             :         }
     909             : 
     910           3 :         if ( !bFound )
     911             :         {
     912           3 :             nGroupPos = nPos+1;
     913          12 :             while ( nGroupPos < nItemCount )
     914             :             {
     915           6 :                 pGroupData = pItemList->GetDataFromPos( nGroupPos );
     916           6 :                 if ( pGroupData->nBits & MenuItemBits::RADIOCHECK )
     917             :                 {
     918           6 :                     if ( IsItemChecked( pGroupData->nId ) )
     919             :                     {
     920           0 :                         CheckItem( pGroupData->nId, false );
     921           0 :                         break;
     922             :                     }
     923             :                 }
     924             :                 else
     925           0 :                     break;
     926           6 :                 nGroupPos++;
     927             :             }
     928             :         }
     929             :     }
     930             : 
     931         811 :     pData->bChecked = bCheck;
     932             : 
     933             :     // update native menu
     934         811 :     if( ImplGetSalMenu() )
     935           0 :         ImplGetSalMenu()->CheckItem( nPos, bCheck );
     936             : 
     937         811 :     ImplCallEventListeners( bCheck ? VCLEVENT_MENU_ITEMCHECKED : VCLEVENT_MENU_ITEMUNCHECKED, nPos );
     938             : }
     939             : 
     940       11862 : bool Menu::IsItemChecked( sal_uInt16 nItemId ) const
     941             : {
     942             :     size_t          nPos;
     943       11862 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     944             : 
     945       11862 :     if ( !pData )
     946           0 :         return false;
     947             : 
     948       11862 :     return pData->bChecked;
     949             : }
     950             : 
     951        5538 : void Menu::EnableItem( sal_uInt16 nItemId, bool bEnable )
     952             : {
     953             :     size_t          nPos;
     954        5538 :     MenuItemData*   pItemData = pItemList->GetData( nItemId, nPos );
     955             : 
     956        5538 :     if ( pItemData && ( pItemData->bEnabled != bEnable ) )
     957             :     {
     958        5407 :         pItemData->bEnabled = bEnable;
     959             : 
     960        5407 :         vcl::Window* pWin = ImplGetWindow();
     961        5407 :         if ( pWin && pWin->IsVisible() )
     962             :         {
     963             :             DBG_ASSERT(IsMenuBar(), "Menu::EnableItem - Popup visible!" );
     964           0 :             long nX = 0;
     965           0 :             size_t nCount = pItemList->size();
     966           0 :             for ( size_t n = 0; n < nCount; n++ )
     967             :             {
     968           0 :                 MenuItemData* pData = pItemList->GetDataFromPos( n );
     969           0 :                 if ( n == nPos )
     970             :                 {
     971           0 :                     pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
     972           0 :                     break;
     973             :                 }
     974           0 :                 nX += pData->aSz.Width();
     975             :             }
     976             :         }
     977             :         // update native menu
     978        5407 :         if( ImplGetSalMenu() )
     979           5 :             ImplGetSalMenu()->EnableItem( nPos, bEnable );
     980             : 
     981        5407 :         ImplCallEventListeners( bEnable ? VCLEVENT_MENU_ENABLE : VCLEVENT_MENU_DISABLE, nPos );
     982             :     }
     983        5538 : }
     984             : 
     985       12949 : bool Menu::IsItemEnabled( sal_uInt16 nItemId ) const
     986             : {
     987             :     size_t          nPos;
     988       12949 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
     989             : 
     990       12949 :     if ( !pData )
     991           0 :         return false;
     992             : 
     993       12949 :     return pData->bEnabled;
     994             : }
     995             : 
     996         238 : void Menu::ShowItem( sal_uInt16 nItemId, bool bVisible )
     997             : {
     998             :     size_t          nPos;
     999         238 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1000             : 
    1001             :     DBG_ASSERT(!IsMenuBar(), "Menu::ShowItem - ignored for menu bar entries!");
    1002         238 :     if (!IsMenuBar()&& pData && (pData->bVisible != bVisible))
    1003             :     {
    1004           0 :         vcl::Window* pWin = ImplGetWindow();
    1005           0 :         if ( pWin && pWin->IsVisible() )
    1006             :         {
    1007             :             DBG_ASSERT( false, "Menu::ShowItem - ignored for visible popups!" );
    1008           0 :             return;
    1009             :         }
    1010           0 :         pData->bVisible = bVisible;
    1011             : 
    1012             :         // update native menu
    1013           0 :         if( ImplGetSalMenu() )
    1014           0 :             ImplGetSalMenu()->ShowItem( nPos, bVisible );
    1015             :     }
    1016             : }
    1017             : 
    1018        5647 : void Menu::SetItemText( sal_uInt16 nItemId, const OUString& rStr )
    1019             : {
    1020             :     size_t          nPos;
    1021        5647 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1022             : 
    1023        5647 :     if ( !pData )
    1024        5647 :         return;
    1025             : 
    1026        5647 :     if ( !rStr.equals( pData->aText ) )
    1027             :     {
    1028        5647 :         pData->aText = rStr;
    1029        5647 :         ImplSetMenuItemData( pData );
    1030             :         // update native menu
    1031        5647 :         if( ImplGetSalMenu() && pData->pSalMenuItem )
    1032           7 :             ImplGetSalMenu()->SetItemText( nPos, pData->pSalMenuItem, rStr );
    1033             : 
    1034        5647 :         vcl::Window* pWin = ImplGetWindow();
    1035        5647 :         delete mpLayoutData, mpLayoutData = NULL;
    1036        5647 :         if (pWin && IsMenuBar())
    1037             :         {
    1038          54 :             ImplCalcSize( pWin );
    1039          54 :             if ( pWin->IsVisible() )
    1040          54 :                 pWin->Invalidate();
    1041             :         }
    1042             : 
    1043        5647 :         ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED, nPos );
    1044             :     }
    1045             : }
    1046             : 
    1047       11757 : OUString Menu::GetItemText( sal_uInt16 nItemId ) const
    1048             : {
    1049             :     size_t          nPos;
    1050       11757 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1051             : 
    1052       11757 :     if ( pData )
    1053       11757 :         return pData->aText;
    1054             : 
    1055           0 :     return OUString();
    1056             : }
    1057             : 
    1058       21888 : void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
    1059             : {
    1060             :     size_t          nPos;
    1061       21888 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1062             : 
    1063       21888 :     if ( !pData )
    1064       21888 :         return;
    1065             : 
    1066       21888 :     pData->aImage = rImage;
    1067       21888 :     ImplSetMenuItemData( pData );
    1068             : 
    1069             :     // update native menu
    1070       21888 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
    1071          36 :         ImplGetSalMenu()->SetItemImage( nPos, pData->pSalMenuItem, rImage );
    1072             : }
    1073             : 
    1074           0 : static inline Image ImplRotImage( const Image& rImage, long nAngle10 )
    1075             : {
    1076           0 :     Image       aRet;
    1077           0 :     BitmapEx    aBmpEx( rImage.GetBitmapEx() );
    1078             : 
    1079           0 :     aBmpEx.Rotate( nAngle10, COL_WHITE );
    1080             : 
    1081           0 :     return Image( aBmpEx );
    1082             : }
    1083             : 
    1084           0 : void Menu::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
    1085             : {
    1086             :     size_t          nPos;
    1087           0 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1088             : 
    1089           0 :     if ( pData )
    1090             :     {
    1091           0 :         long nDeltaAngle = (nAngle10 - pData->nItemImageAngle) % 3600;
    1092           0 :         while( nDeltaAngle < 0 )
    1093           0 :             nDeltaAngle += 3600;
    1094             : 
    1095           0 :         pData->nItemImageAngle = nAngle10;
    1096           0 :         if( nDeltaAngle && !!pData->aImage )
    1097           0 :             pData->aImage = ImplRotImage( pData->aImage, nDeltaAngle );
    1098             :     }
    1099           0 : }
    1100             : 
    1101           0 : static inline Image ImplMirrorImage( const Image& rImage )
    1102             : {
    1103           0 :     Image       aRet;
    1104           0 :     BitmapEx    aBmpEx( rImage.GetBitmapEx() );
    1105             : 
    1106           0 :     aBmpEx.Mirror( BmpMirrorFlags::Horizontal );
    1107             : 
    1108           0 :     return Image( aBmpEx );
    1109             : }
    1110             : 
    1111           0 : void Menu::SetItemImageMirrorMode( sal_uInt16 nItemId, bool bMirror )
    1112             : {
    1113             :     size_t          nPos;
    1114           0 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1115             : 
    1116           0 :     if ( pData )
    1117             :     {
    1118           0 :         if( ( pData->bMirrorMode && ! bMirror ) ||
    1119           0 :             ( ! pData->bMirrorMode && bMirror )
    1120             :             )
    1121             :         {
    1122           0 :             pData->bMirrorMode = bMirror;
    1123           0 :             if( !!pData->aImage )
    1124           0 :                 pData->aImage = ImplMirrorImage( pData->aImage );
    1125             :         }
    1126             :     }
    1127           0 : }
    1128             : 
    1129         983 : Image Menu::GetItemImage( sal_uInt16 nItemId ) const
    1130             : {
    1131         983 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1132             : 
    1133         983 :     if ( pData )
    1134         983 :         return pData->aImage;
    1135             :     else
    1136           0 :         return Image();
    1137             : }
    1138             : 
    1139      256514 : void Menu::SetItemCommand( sal_uInt16 nItemId, const OUString& rCommand )
    1140             : {
    1141             :     size_t        nPos;
    1142      256514 :     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
    1143             : 
    1144      256514 :     if ( pData )
    1145      256514 :         pData->aCommandStr = rCommand;
    1146      256514 : }
    1147             : 
    1148      293907 : OUString Menu::GetItemCommand( sal_uInt16 nItemId ) const
    1149             : {
    1150      293907 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1151             : 
    1152      293907 :     if (pData)
    1153      293907 :         return pData->aCommandStr;
    1154             : 
    1155           0 :     return OUString();
    1156             : }
    1157             : 
    1158       65564 : void Menu::SetHelpCommand( sal_uInt16 nItemId, const OUString& rStr )
    1159             : {
    1160       65564 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1161             : 
    1162       65564 :     if ( pData )
    1163       65564 :         pData->aHelpCommandStr = rStr;
    1164       65564 : }
    1165             : 
    1166       58292 : OUString Menu::GetHelpCommand( sal_uInt16 nItemId ) const
    1167             : {
    1168       58292 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1169             : 
    1170       58292 :     if ( pData )
    1171       58292 :         return pData->aHelpCommandStr;
    1172             : 
    1173           0 :     return OUString();
    1174             : }
    1175             : 
    1176       12432 : void Menu::SetHelpText( sal_uInt16 nItemId, const OUString& rStr )
    1177             : {
    1178       12432 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1179             : 
    1180       12432 :     if ( pData )
    1181       12432 :         pData->aHelpText = rStr;
    1182       12432 : }
    1183             : 
    1184         269 : OUString Menu::ImplGetHelpText( sal_uInt16 nItemId ) const
    1185             : {
    1186         269 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1187             : 
    1188         807 :     if ( pData && pData->aHelpText.isEmpty() &&
    1189         538 :          (( !pData->aHelpId.isEmpty()  ) || ( !pData->aCommandStr.isEmpty() )))
    1190             :     {
    1191         269 :         Help* pHelp = Application::GetHelp();
    1192         269 :         if ( pHelp )
    1193             :         {
    1194         269 :             if (!pData->aCommandStr.isEmpty())
    1195         269 :                 pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, NULL );
    1196         269 :             if (pData->aHelpText.isEmpty() && !pData->aHelpId.isEmpty())
    1197           0 :                 pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
    1198             :         }
    1199             :     }
    1200             : 
    1201         269 :     return OUString();
    1202             : }
    1203             : 
    1204         269 : OUString Menu::GetHelpText( sal_uInt16 nItemId ) const
    1205             : {
    1206         269 :     return ImplGetHelpText( nItemId );
    1207             : }
    1208             : 
    1209           0 : void Menu::SetTipHelpText( sal_uInt16 nItemId, const OUString& rStr )
    1210             : {
    1211           0 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1212             : 
    1213           0 :     if ( pData )
    1214           0 :         pData->aTipHelpText = rStr;
    1215           0 : }
    1216             : 
    1217           2 : OUString Menu::GetTipHelpText( sal_uInt16 nItemId ) const
    1218             : {
    1219           2 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1220             : 
    1221           2 :     if ( pData )
    1222           2 :         return pData->aTipHelpText;
    1223             : 
    1224           0 :     return OUString();
    1225             : }
    1226             : 
    1227        8242 : void Menu::SetHelpId( sal_uInt16 nItemId, const OString& rHelpId )
    1228             : {
    1229        8242 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1230             : 
    1231        8242 :     if ( pData )
    1232        8241 :         pData->aHelpId = rHelpId;
    1233        8242 : }
    1234             : 
    1235           0 : OString Menu::GetHelpId( sal_uInt16 nItemId ) const
    1236             : {
    1237           0 :     OString aRet;
    1238             : 
    1239           0 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1240             : 
    1241           0 :     if ( pData )
    1242             :     {
    1243           0 :         if ( !pData->aHelpId.isEmpty() )
    1244           0 :             aRet = pData->aHelpId;
    1245             :         else
    1246           0 :             aRet = OUStringToOString( pData->aCommandStr, RTL_TEXTENCODING_UTF8 );
    1247             :     }
    1248             : 
    1249           0 :     return aRet;
    1250             : }
    1251             : 
    1252         606 : Menu& Menu::operator=( const Menu& rMenu )
    1253             : {
    1254             :     // clean up
    1255         606 :     Clear();
    1256             : 
    1257             :     // copy items
    1258         606 :     sal_uInt16 nCount = rMenu.GetItemCount();
    1259        9696 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
    1260        9090 :         ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
    1261             : 
    1262         606 :     nDefaultItem = rMenu.nDefaultItem;
    1263         606 :     aActivateHdl = rMenu.aActivateHdl;
    1264         606 :     aDeactivateHdl = rMenu.aDeactivateHdl;
    1265         606 :     aHighlightHdl = rMenu.aHighlightHdl;
    1266         606 :     aSelectHdl = rMenu.aSelectHdl;
    1267         606 :     aTitleText = rMenu.aTitleText;
    1268         606 :     nTitleHeight = rMenu.nTitleHeight;
    1269             : 
    1270         606 :     return *this;
    1271             : }
    1272             : 
    1273       24983 : bool Menu::ImplIsVisible( sal_uInt16 nPos ) const
    1274             : {
    1275       24983 :     bool bVisible = true;
    1276             : 
    1277       24983 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    1278             :     // check general visibility first
    1279       24983 :     if( pData && !pData->bVisible )
    1280           0 :         bVisible = false;
    1281             : 
    1282       24983 :     if ( bVisible && pData && pData->eType == MenuItemType::SEPARATOR )
    1283             :     {
    1284         166 :         if( nPos == 0 ) // no separator should be shown at the very beginning
    1285           0 :             bVisible = false;
    1286             :         else
    1287             :         {
    1288             :             // always avoid adjacent separators
    1289         166 :             size_t nCount = pItemList->size();
    1290             :             size_t n;
    1291         166 :             MenuItemData* pNextData = NULL;
    1292             :             // search next visible item
    1293         166 :             for( n = nPos + 1; n < nCount; n++ )
    1294             :             {
    1295         166 :                 pNextData = pItemList->GetDataFromPos( n );
    1296         166 :                 if( pNextData && pNextData->bVisible )
    1297             :                 {
    1298         166 :                     if( pNextData->eType == MenuItemType::SEPARATOR || ImplIsVisible(n) )
    1299         166 :                         break;
    1300             :                 }
    1301             :             }
    1302         166 :             if( n == nCount ) // no next visible item
    1303           0 :                 bVisible = false;
    1304             :             // check for separator
    1305         166 :             if( pNextData && pNextData->bVisible && pNextData->eType == MenuItemType::SEPARATOR )
    1306           0 :                 bVisible = false;
    1307             : 
    1308         166 :             if( bVisible )
    1309             :             {
    1310         166 :                 for( n = nPos; n > 0; n-- )
    1311             :                 {
    1312         166 :                     pNextData = pItemList->GetDataFromPos( n-1 );
    1313         166 :                     if( pNextData && pNextData->bVisible )
    1314             :                     {
    1315         166 :                         if( pNextData->eType != MenuItemType::SEPARATOR && ImplIsVisible(n-1) )
    1316         166 :                             break;
    1317             :                     }
    1318             :                 }
    1319         166 :                 if( n == 0 ) // no previous visible item
    1320           0 :                     bVisible = false;
    1321             :             }
    1322             :         }
    1323             :     }
    1324             : 
    1325             :     // not allowed for menubar, as I do not know
    1326             :     // whether a menu-entry will disappear or will appear
    1327       49966 :     if (bVisible && !IsMenuBar() && (nMenuFlags & MenuFlags::HideDisabledEntries) &&
    1328       24983 :         !(nMenuFlags & MenuFlags::AlwaysShowDisabledEntries))
    1329             :     {
    1330           0 :         if( !pData ) // e.g. nPos == ITEMPOS_INVALID
    1331           0 :             bVisible = false;
    1332           0 :         else if ( pData->eType != MenuItemType::SEPARATOR ) // separators handled above
    1333             :         {
    1334             :             // tdf#86850 Always display clipboard functions
    1335           0 :             if ( pData->nId == SID_CUT || pData->nId == SID_COPY || pData->nId == SID_PASTE || pData->nId == SID_MENU_PASTE_SPECIAL )
    1336           0 :                 bVisible = true;
    1337             :             else
    1338             :                 // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( true ) );
    1339           0 :                 bVisible = pData->bEnabled; // do not check submenus as they might be filled at Activate().
    1340             :         }
    1341             :     }
    1342             : 
    1343       24983 :     return bVisible;
    1344             : }
    1345             : 
    1346        5655 : bool Menu::IsItemPosVisible( sal_uInt16 nItemPos ) const
    1347             : {
    1348        5655 :     return IsMenuVisible() && ImplIsVisible( nItemPos );
    1349             : }
    1350             : 
    1351        5691 : bool Menu::IsMenuVisible() const
    1352             : {
    1353        5691 :     return pWindow && pWindow->IsReallyVisible();
    1354             : }
    1355             : 
    1356           0 : bool Menu::ImplIsSelectable( sal_uInt16 nPos ) const
    1357             : {
    1358           0 :     bool bSelectable = true;
    1359             : 
    1360           0 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    1361             :     // check general visibility first
    1362           0 :     if ( pData && ( pData->nBits & MenuItemBits::NOSELECT ) )
    1363           0 :         bSelectable = false;
    1364             : 
    1365           0 :     return bSelectable;
    1366             : }
    1367             : 
    1368        5432 : css::uno::Reference<css::accessibility::XAccessible> Menu::GetAccessible()
    1369             : {
    1370             :     // Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
    1371             :     // overwritten and may contain a disposed object when the initial menubar gets set again. So use the
    1372             :     // mxAccessible member only for sub menus.
    1373        5432 :     if ( pStartedFrom )
    1374             :     {
    1375        3914 :         for ( sal_uInt16 i = 0, nCount = pStartedFrom->GetItemCount(); i < nCount; ++i )
    1376             :         {
    1377        3914 :             sal_uInt16 nItemId = pStartedFrom->GetItemId( i );
    1378        3914 :             if ( static_cast< Menu* >( pStartedFrom->GetPopupMenu( nItemId ) ) == this )
    1379             :             {
    1380        1306 :                 css::uno::Reference<css::accessibility::XAccessible> xParent = pStartedFrom->GetAccessible();
    1381        1306 :                 if ( xParent.is() )
    1382             :                 {
    1383        1306 :                     css::uno::Reference<css::accessibility::XAccessibleContext> xParentContext( xParent->getAccessibleContext() );
    1384        1306 :                     if (xParentContext.is())
    1385        1306 :                         return xParentContext->getAccessibleChild( i );
    1386           0 :                 }
    1387             :             }
    1388             :         }
    1389             :     }
    1390        4126 :     else if ( !mxAccessible.is() )
    1391             :     {
    1392          25 :         UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
    1393          25 :         if ( pWrapper )
    1394          25 :             mxAccessible = pWrapper->CreateAccessible(this, IsMenuBar());
    1395             :     }
    1396             : 
    1397        4126 :     return mxAccessible;
    1398             : }
    1399             : 
    1400         325 : void Menu::SetAccessible(const css::uno::Reference<css::accessibility::XAccessible>& rxAccessible )
    1401             : {
    1402         325 :     mxAccessible = rxAccessible;
    1403         325 : }
    1404             : 
    1405        4601 : Size Menu::ImplGetNativeCheckAndRadioSize(vcl::RenderContext& rRenderContext, long& rCheckHeight, long& rRadioHeight ) const
    1406             : {
    1407        4601 :     long nCheckWidth = 0, nRadioWidth = 0;
    1408        4601 :     rCheckHeight = rRadioHeight = 0;
    1409             : 
    1410        4601 :     if (!IsMenuBar())
    1411             :     {
    1412          17 :         ImplControlValue aVal;
    1413          17 :         Rectangle aNativeBounds;
    1414          17 :         Rectangle aNativeContent;
    1415             : 
    1416          17 :         Rectangle aCtrlRegion(Rectangle(Point(), Size(100, 15)));
    1417          17 :         if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK))
    1418             :         {
    1419           0 :             if (rRenderContext.GetNativeControlRegion(ControlType(CTRL_MENU_POPUP), ControlPart(PART_MENU_ITEM_CHECK_MARK),
    1420             :                                               aCtrlRegion, ControlState(ControlState::ENABLED), aVal, OUString(),
    1421           0 :                                               aNativeBounds, aNativeContent))
    1422             :             {
    1423           0 :                 rCheckHeight = aNativeBounds.GetHeight();
    1424           0 :                 nCheckWidth = aNativeContent.GetWidth();
    1425             :             }
    1426             :         }
    1427          17 :         if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK))
    1428             :         {
    1429           0 :             if (rRenderContext.GetNativeControlRegion(ControlType(CTRL_MENU_POPUP), ControlPart(PART_MENU_ITEM_RADIO_MARK),
    1430             :                                                       aCtrlRegion, ControlState(ControlState::ENABLED), aVal, OUString(),
    1431           0 :                                                       aNativeBounds, aNativeContent))
    1432             :             {
    1433           0 :                 rRadioHeight = aNativeBounds.GetHeight();
    1434           0 :                 nRadioWidth = aNativeContent.GetWidth();
    1435             :             }
    1436          17 :         }
    1437             :     }
    1438        4601 :     return Size(std::max(nCheckWidth, nRadioWidth), std::max(rCheckHeight, rRadioHeight));
    1439             : }
    1440             : 
    1441           0 : bool Menu::ImplGetNativeSubmenuArrowSize(vcl::RenderContext& rRenderContext, Size& rArrowSize, long& rArrowSpacing) const
    1442             : {
    1443           0 :     ImplControlValue aVal;
    1444           0 :     Rectangle aNativeBounds;
    1445           0 :     Rectangle aNativeContent;
    1446           0 :     Rectangle aCtrlRegion(Rectangle(Point(), Size(100, 15)));
    1447           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_SUBMENU_ARROW))
    1448             :     {
    1449           0 :         if (rRenderContext.GetNativeControlRegion(ControlType(CTRL_MENU_POPUP), ControlPart(PART_MENU_SUBMENU_ARROW),
    1450             :                                                   aCtrlRegion, ControlState(ControlState::ENABLED),
    1451           0 :                                                   aVal, OUString(), aNativeBounds, aNativeContent))
    1452             :         {
    1453           0 :             Size aSize(aNativeContent.GetWidth(), aNativeContent.GetHeight());
    1454           0 :             rArrowSize = aSize;
    1455           0 :             rArrowSpacing = aNativeBounds.GetWidth() - aNativeContent.GetWidth();
    1456           0 :             return true;
    1457             :         }
    1458             :     }
    1459           0 :     return false;
    1460             : }
    1461             : 
    1462      427632 : void Menu::ImplAddDel( ImplMenuDelData& rDel )
    1463             : {
    1464             :     DBG_ASSERT( !rDel.mpMenu, "Menu::ImplAddDel(): cannot add ImplMenuDelData twice !" );
    1465      427632 :     if( !rDel.mpMenu )
    1466             :     {
    1467      427632 :         rDel.mpMenu = this;
    1468      427632 :         rDel.mpNext = mpFirstDel;
    1469      427632 :         mpFirstDel = &rDel;
    1470             :     }
    1471      427632 : }
    1472             : 
    1473      427632 : void Menu::ImplRemoveDel( ImplMenuDelData& rDel )
    1474             : {
    1475      427632 :     rDel.mpMenu = NULL;
    1476      427632 :     if ( mpFirstDel == &rDel )
    1477             :     {
    1478      427632 :         mpFirstDel = rDel.mpNext;
    1479             :     }
    1480             :     else
    1481             :     {
    1482           0 :         ImplMenuDelData* pData = mpFirstDel;
    1483           0 :         while ( pData && (pData->mpNext != &rDel) )
    1484           0 :             pData = pData->mpNext;
    1485             : 
    1486             :         DBG_ASSERT( pData, "Menu::ImplRemoveDel(): ImplMenuDelData not registered !" );
    1487           0 :         if( pData )
    1488           0 :             pData->mpNext = rDel.mpNext;
    1489             :     }
    1490      427632 : }
    1491             : 
    1492        3376 : Size Menu::ImplCalcSize( vcl::Window* pWin )
    1493             : {
    1494             :     // | Check/Radio/Image| Text| Accel/Popup|
    1495             : 
    1496             :     // for symbols: nFontHeight x nFontHeight
    1497        3376 :     long nFontHeight = pWin->GetTextHeight();
    1498        3376 :     long nExtra = nFontHeight/4;
    1499             : 
    1500        3376 :     long nMinMenuItemHeight = nFontHeight;
    1501        3376 :     long nCheckHeight = 0, nRadioHeight = 0;
    1502        3376 :     Size aMaxSize = ImplGetNativeCheckAndRadioSize(*pWin, nCheckHeight, nRadioHeight); // FIXME
    1503        3376 :     if( aMaxSize.Height() > nMinMenuItemHeight )
    1504           0 :         nMinMenuItemHeight = aMaxSize.Height();
    1505             : 
    1506        3376 :     Size aMaxImgSz;
    1507             : 
    1508        3376 :     const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
    1509        3376 :     if ( rSettings.GetUseImagesInMenus() )
    1510             :     {
    1511        3376 :         if ( 16 > nMinMenuItemHeight )
    1512        3374 :             nMinMenuItemHeight = 16;
    1513       13249 :         for ( size_t i = pItemList->size(); i; )
    1514             :         {
    1515        6505 :             MenuItemData* pData = pItemList->GetDataFromPos( --i );
    1516       13010 :             if ( ImplIsVisible( i )
    1517        6513 :                && (  ( pData->eType == MenuItemType::IMAGE )
    1518        6505 :                   || ( pData->eType == MenuItemType::STRINGIMAGE )
    1519             :                   )
    1520             :                )
    1521             :             {
    1522           8 :                 Size aImgSz = pData->aImage.GetSizePixel();
    1523           8 :                 if ( aImgSz.Height() > aMaxImgSz.Height() )
    1524           8 :                     aMaxImgSz.Height() = aImgSz.Height();
    1525           8 :                 if ( aImgSz.Height() > nMinMenuItemHeight )
    1526           0 :                     nMinMenuItemHeight = aImgSz.Height();
    1527           8 :                 break;
    1528             :             }
    1529             :         }
    1530             :     }
    1531             : 
    1532        3376 :     Size aSz;
    1533        3376 :     long nCheckWidth = 0;
    1534        3376 :     long nMaxWidth = 0;
    1535             : 
    1536       13475 :     for ( size_t n = pItemList->size(); n; )
    1537             :     {
    1538        6723 :         MenuItemData* pData = pItemList->GetDataFromPos( --n );
    1539             : 
    1540        6723 :         pData->aSz.Height() = 0;
    1541        6723 :         pData->aSz.Width() = 0;
    1542             : 
    1543        6723 :         if ( ImplIsVisible( n ) )
    1544             :         {
    1545        6723 :             long nWidth = 0;
    1546             : 
    1547             :             // Separator
    1548        6723 :             if (!IsMenuBar()&& (pData->eType == MenuItemType::SEPARATOR))
    1549             :             {
    1550             :                 //Useless: DBG_ASSERT( !IsMenuBar(), "Separator in MenuBar ?! " );
    1551          43 :                 pData->aSz.Height() = 4;
    1552             :             }
    1553             : 
    1554             :             // Image:
    1555        6723 :             if (!IsMenuBar() && ((pData->eType == MenuItemType::IMAGE) || (pData->eType == MenuItemType::STRINGIMAGE)))
    1556             :             {
    1557          97 :                 Size aImgSz = pData->aImage.GetSizePixel();
    1558             : 
    1559          97 :                 sal_Int32 nScaleFactor = pWindow->GetDPIScaleFactor();
    1560          97 :                 aImgSz.Height() *= nScaleFactor;
    1561          97 :                 aImgSz.Width() *= nScaleFactor;
    1562             : 
    1563          97 :                 aImgSz.Height() += 4; // add a border for native marks
    1564          97 :                 aImgSz.Width() += 4; // add a border for native marks
    1565          97 :                 if ( aImgSz.Width() > aMaxImgSz.Width() )
    1566           8 :                     aMaxImgSz.Width() = aImgSz.Width();
    1567          97 :                 if ( aImgSz.Height() > aMaxImgSz.Height() )
    1568           8 :                     aMaxImgSz.Height() = aImgSz.Height();
    1569          97 :                 if ( aImgSz.Height() > pData->aSz.Height() )
    1570          97 :                     pData->aSz.Height() = aImgSz.Height();
    1571             :             }
    1572             : 
    1573             :             // Check Buttons:
    1574        6723 :             if (!IsMenuBar() && pData->HasCheck())
    1575             :             {
    1576          60 :                 nCheckWidth = aMaxSize.Width();
    1577             :                 // checks / images take the same place
    1578          60 :                 if( ! ( ( pData->eType == MenuItemType::IMAGE ) || ( pData->eType == MenuItemType::STRINGIMAGE ) ) )
    1579          21 :                     nWidth += nCheckWidth + nExtra * 2;
    1580             :             }
    1581             : 
    1582             :             // Text:
    1583        6723 :             if ( (pData->eType == MenuItemType::STRING) || (pData->eType == MenuItemType::STRINGIMAGE) )
    1584             :             {
    1585        6680 :                 long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
    1586        6680 :                 long nTextHeight = pWin->GetTextHeight();
    1587             : 
    1588        6680 :                 if (IsMenuBar())
    1589             :                 {
    1590        6494 :                     if ( nTextHeight > pData->aSz.Height() )
    1591        6494 :                         pData->aSz.Height() = nTextHeight;
    1592             : 
    1593        6494 :                     pData->aSz.Width() = nTextWidth + 4*nExtra;
    1594        6494 :                     aSz.Width() += pData->aSz.Width();
    1595             :                 }
    1596             :                 else
    1597         186 :                     pData->aSz.Height() = std::max( std::max( nTextHeight, pData->aSz.Height() ), nMinMenuItemHeight );
    1598             : 
    1599        6680 :                 nWidth += nTextWidth;
    1600             :             }
    1601             : 
    1602             :             // Accel
    1603        6723 :             if (!IsMenuBar()&& pData->aAccelKey.GetCode() && !ImplAccelDisabled())
    1604             :             {
    1605           0 :                 OUString aName = pData->aAccelKey.GetName();
    1606           0 :                 long nAccWidth = pWin->GetTextWidth( aName );
    1607           0 :                 nAccWidth += nExtra;
    1608           0 :                 nWidth += nAccWidth;
    1609             :             }
    1610             : 
    1611             :             // SubMenu?
    1612        6723 :             if (!IsMenuBar() && pData->pSubMenu)
    1613             :             {
    1614          37 :                     if ( nFontHeight > nWidth )
    1615           0 :                         nWidth += nFontHeight;
    1616             : 
    1617          37 :                 pData->aSz.Height() = std::max( std::max( nFontHeight, pData->aSz.Height() ), nMinMenuItemHeight );
    1618             :             }
    1619             : 
    1620        6723 :             pData->aSz.Height() += EXTRAITEMHEIGHT; // little bit more distance
    1621             : 
    1622        6723 :             if (!IsMenuBar())
    1623         229 :                 aSz.Height() += (long)pData->aSz.Height();
    1624             : 
    1625        6723 :             if ( nWidth > nMaxWidth )
    1626        1370 :                 nMaxWidth = nWidth;
    1627             : 
    1628             :         }
    1629             :     }
    1630             : 
    1631             :     // Additional space for title
    1632        3376 :     nTitleHeight = 0;
    1633        3376 :     if (!IsMenuBar() && aTitleText.getLength() > 0) {
    1634             :         // Vertically, one height of char + extra space for decoration
    1635           0 :         nTitleHeight = nFontHeight + 4 * SPACE_AROUND_TITLE ;
    1636           0 :         aSz.Height() += nTitleHeight;
    1637             : 
    1638             :         // Horizontally, compute text width with bold font
    1639           0 :         pWin->Push(PushFlags::FONT);
    1640           0 :         vcl::Font aFont = pWin->GetFont();
    1641           0 :         aFont.SetWeight(WEIGHT_BOLD);
    1642           0 :         pWin->SetFont(aFont);
    1643           0 :         long nWidth = pWin->GetTextWidth( aTitleText ) + 4 * SPACE_AROUND_TITLE;
    1644           0 :         pWin->Pop();
    1645           0 :         if ( nWidth > nMaxWidth )
    1646           0 :             nMaxWidth = nWidth;
    1647             :     }
    1648             : 
    1649        3376 :     if (!IsMenuBar())
    1650             :     {
    1651             :         // popup menus should not be wider than half the screen
    1652             :         // except on rather small screens
    1653             :         // TODO: move GetScreenNumber from SystemWindow to Window ?
    1654             :         // currently we rely on internal privileges
    1655           8 :         unsigned int nDisplayScreen = pWin->ImplGetWindowImpl()->mpFrame->maGeometry.nDisplayScreenNumber;
    1656           8 :         Rectangle aDispRect( Application::GetScreenPosSizePixel( nDisplayScreen ) );
    1657           8 :         long nScreenWidth = aDispRect.GetWidth() >= 800 ? aDispRect.GetWidth() : 800;
    1658           8 :         if( nMaxWidth > nScreenWidth/2 )
    1659           0 :             nMaxWidth = nScreenWidth/2;
    1660             : 
    1661           8 :         sal_uInt16 gfxExtra = (sal_uInt16) std::max( nExtra, 7L ); // #107710# increase space between checkmarks/images/text
    1662           8 :         nImgOrChkPos = (sal_uInt16)nExtra;
    1663           8 :         long nImgOrChkWidth = 0;
    1664           8 :         if( aMaxSize.Height() > 0 ) // NWF case
    1665           0 :             nImgOrChkWidth = aMaxSize.Height() + nExtra;
    1666             :         else // non NWF case
    1667           8 :             nImgOrChkWidth = nFontHeight/2 + gfxExtra;
    1668           8 :         nImgOrChkWidth = std::max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra );
    1669           8 :         nTextPos = (sal_uInt16)(nImgOrChkPos + nImgOrChkWidth);
    1670           8 :         nTextPos = nTextPos + gfxExtra;
    1671             : 
    1672           8 :         aSz.Width() = nTextPos + nMaxWidth + nExtra;
    1673           8 :         aSz.Width() += 4*nExtra;   // a _little_ more ...
    1674             : 
    1675           8 :         aSz.Width() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    1676           8 :         aSz.Height() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    1677             :     }
    1678             :     else
    1679             :     {
    1680        3368 :         nTextPos = (sal_uInt16)(2*nExtra);
    1681        3368 :         aSz.Height() = nFontHeight+6;
    1682             : 
    1683             :         // get menubar height from native methods if supported
    1684        3368 :         if( pWindow->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
    1685             :         {
    1686           2 :             ImplControlValue aVal;
    1687           2 :             Rectangle aNativeBounds;
    1688           2 :             Rectangle aNativeContent;
    1689           2 :             Point tmp( 0, 0 );
    1690           2 :             Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
    1691           6 :             if( pWindow->GetNativeControlRegion( ControlType(CTRL_MENUBAR),
    1692             :                                                  ControlPart(PART_ENTIRE_CONTROL),
    1693             :                                                  aCtrlRegion,
    1694             :                                                  ControlState(ControlState::ENABLED),
    1695             :                                                  aVal,
    1696             :                                                  OUString(),
    1697             :                                                  aNativeBounds,
    1698           6 :                                                  aNativeContent )
    1699             :             )
    1700             :             {
    1701           2 :                 int nNativeHeight = aNativeBounds.GetHeight();
    1702           2 :                 if( nNativeHeight > aSz.Height() )
    1703           2 :                     aSz.Height() = nNativeHeight;
    1704           2 :             }
    1705             :         }
    1706             : 
    1707             :         // account for the size of the close button, which actually is a toolbox
    1708             :         // due to NWF this is variable
    1709        3368 :         long nCloseButtonHeight = static_cast<MenuBarWindow*>(pWindow.get())->MinCloseButtonSize().Height();
    1710        3368 :         if (aSz.Height() < nCloseButtonHeight)
    1711           2 :             aSz.Height() = nCloseButtonHeight;
    1712             :     }
    1713             : 
    1714        3376 :     if ( pLogo )
    1715           0 :         aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
    1716             : 
    1717        3376 :     return aSz;
    1718             : }
    1719             : 
    1720          27 : static void ImplPaintCheckBackground(vcl::RenderContext& rRenderContext, vcl::Window& rWindow, const Rectangle& i_rRect, bool i_bHighlight)
    1721             : {
    1722          27 :     bool bNativeOk = false;
    1723          27 :     if (rRenderContext.IsNativeControlSupported(CTRL_TOOLBAR, PART_BUTTON))
    1724             :     {
    1725           0 :         ImplControlValue    aControlValue;
    1726           0 :         Rectangle           aCtrlRegion( i_rRect );
    1727           0 :         ControlState        nState = ControlState::PRESSED | ControlState::ENABLED;
    1728             : 
    1729           0 :         aControlValue.setTristateVal(BUTTONVALUE_ON);
    1730             : 
    1731             :         bNativeOk = rRenderContext.DrawNativeControl(CTRL_TOOLBAR, PART_BUTTON,
    1732             :                                                      aCtrlRegion, nState, aControlValue,
    1733           0 :                                                      OUString());
    1734             :     }
    1735             : 
    1736          27 :     if (!bNativeOk)
    1737             :     {
    1738          27 :         const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
    1739          27 :         Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
    1740          27 :         RenderTools::DrawSelectionBackground(rRenderContext, rWindow, i_rRect, 0, i_bHighlight, true, false, NULL, 2, &aColor);
    1741             :     }
    1742          27 : }
    1743             : 
    1744       10810 : static OUString getShortenedString( const OUString& i_rLong, vcl::RenderContext& rRenderContext, long i_nMaxWidth )
    1745             : {
    1746       10810 :     sal_Int32 nPos = -1;
    1747       10810 :     OUString aNonMnem(OutputDevice::GetNonMnemonicString(i_rLong, nPos));
    1748       10810 :     aNonMnem = rRenderContext.GetEllipsisString( aNonMnem, i_nMaxWidth, DrawTextFlags::CenterEllipsis);
    1749             :     // re-insert mnemonic
    1750       10810 :     if (nPos != -1)
    1751             :     {
    1752       10792 :         if (nPos < aNonMnem.getLength() && i_rLong[nPos+1] == aNonMnem[nPos])
    1753             :         {
    1754       10792 :             OUStringBuffer aBuf( i_rLong.getLength() );
    1755       10792 :             aBuf.append( aNonMnem.copy( 0, nPos) );
    1756       10792 :             aBuf.append( '~' );
    1757       10792 :             aBuf.append( aNonMnem.copy(nPos) );
    1758       10792 :             aNonMnem = aBuf.makeStringAndClear();
    1759             :         }
    1760             :     }
    1761       10810 :     return aNonMnem;
    1762             : }
    1763             : 
    1764           0 : void Menu::ImplPaintMenuTitle(vcl::RenderContext& rRenderContext, const Rectangle& rRect ) const
    1765             : {
    1766             :     // Save previous graphical settings, set new one
    1767           0 :     rRenderContext.Push(PushFlags::FONT | PushFlags::FILLCOLOR);
    1768           0 :     Wallpaper aOldBackground = rRenderContext.GetBackground();
    1769             : 
    1770           0 :     Color aBackgroundColor = rRenderContext.GetSettings().GetStyleSettings().GetMenuBarColor();
    1771           0 :     rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
    1772           0 :     rRenderContext.SetFillColor(aBackgroundColor);
    1773           0 :     vcl::Font aFont = rRenderContext.GetFont();
    1774           0 :     aFont.SetWeight(WEIGHT_BOLD);
    1775           0 :     rRenderContext.SetFont(aFont);
    1776             : 
    1777             :     // Draw background rectangle
    1778           0 :     Rectangle aBgRect(rRect);
    1779           0 :     int nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    1780           0 :     aBgRect.setX(aBgRect.getX() + SPACE_AROUND_TITLE);
    1781           0 :     aBgRect.setWidth(aBgRect.getWidth() - 2 * SPACE_AROUND_TITLE - 2 * nOuterSpaceX);
    1782           0 :     aBgRect.setY(aBgRect.getY() + SPACE_AROUND_TITLE);
    1783           0 :     aBgRect.setHeight(nTitleHeight - 2 * SPACE_AROUND_TITLE);
    1784           0 :     rRenderContext.DrawRect(aBgRect);
    1785             : 
    1786             :     // Draw the text centered
    1787           0 :     Point aTextTopLeft(rRect.TopLeft());
    1788           0 :     long textWidth = rRenderContext.GetTextWidth(aTitleText);
    1789           0 :     aTextTopLeft.X() += (aBgRect.getWidth() - textWidth) / 2;
    1790           0 :     aTextTopLeft.Y() += SPACE_AROUND_TITLE;
    1791           0 :     rRenderContext.DrawText(aTextTopLeft, aTitleText, 0, aTitleText.getLength());
    1792             : 
    1793             :     // Restore
    1794           0 :     rRenderContext.Pop();
    1795           0 :     rRenderContext.SetBackground(aOldBackground);
    1796           0 : }
    1797             : 
    1798        1225 : void Menu::ImplPaint(vcl::RenderContext& rRenderContext,
    1799             :                      sal_uInt16 nBorder, long nStartY, MenuItemData* pThisItemOnly,
    1800             :                      bool bHighlighted, bool bLayout, bool bRollover) const
    1801             : {
    1802             :     // for symbols: nFontHeight x nFontHeight
    1803        1225 :     long nFontHeight = rRenderContext.GetTextHeight();
    1804        1225 :     long nExtra = nFontHeight / 4;
    1805             : 
    1806        1225 :     long nCheckHeight = 0, nRadioHeight = 0;
    1807        1225 :     ImplGetNativeCheckAndRadioSize(rRenderContext, nCheckHeight, nRadioHeight);
    1808             : 
    1809        1225 :     DecorationView aDecoView(&rRenderContext);
    1810        1225 :     const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
    1811             : 
    1812        1225 :     Point aTopLeft, aTmpPos;
    1813             : 
    1814        1225 :     if (pLogo)
    1815           0 :         aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
    1816             : 
    1817        1225 :     int nOuterSpaceX = 0;
    1818        1225 :     if (!IsMenuBar())
    1819             :     {
    1820           9 :         nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    1821           9 :         aTopLeft.X() += nOuterSpaceX;
    1822           9 :         aTopLeft.Y() += ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    1823             :     }
    1824             : 
    1825        1225 :     Size aOutSz = rRenderContext.GetOutputSizePixel();
    1826        1225 :     size_t nCount = pItemList->size();
    1827        1225 :     if (bLayout)
    1828           2 :         mpLayoutData->m_aVisibleItemBoundRects.clear();
    1829             : 
    1830             :     // Paint title
    1831        1225 :     if (!pThisItemOnly && !IsMenuBar() && nTitleHeight > 0)
    1832           0 :         ImplPaintMenuTitle(rRenderContext, Rectangle(aTopLeft, aOutSz));
    1833             : 
    1834       12148 :     for (size_t n = 0; n < nCount; n++)
    1835             :     {
    1836       10923 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
    1837       10923 :         if (ImplIsVisible(n) && (!pThisItemOnly || (pData == pThisItemOnly)))
    1838             :         {
    1839       10859 :             if (pThisItemOnly)
    1840             :             {
    1841           8 :                 if (IsMenuBar())
    1842             :                 {
    1843           8 :                     if (bRollover)
    1844           0 :                         rRenderContext.SetTextColor(rSettings.GetMenuBarRolloverTextColor());
    1845           8 :                     else if (bHighlighted)
    1846           8 :                         rRenderContext.SetTextColor(rSettings.GetMenuBarHighlightTextColor());
    1847             :                 }
    1848             :                 else
    1849             :                 {
    1850           0 :                     if (bHighlighted)
    1851           0 :                         rRenderContext.SetTextColor(rSettings.GetMenuHighlightTextColor());
    1852             :                 }
    1853             :             }
    1854             : 
    1855       10859 :             Point aPos(aTopLeft);
    1856       10859 :             aPos.Y() += nBorder;
    1857       10859 :             aPos.Y() += nStartY;
    1858             : 
    1859       10859 :             if (aPos.Y() >= 0)
    1860             :             {
    1861       10859 :                 long nTextOffsetY = ((pData->aSz.Height() - nFontHeight) / 2);
    1862       10859 :                 if (IsMenuBar())
    1863       10602 :                     nTextOffsetY += (aOutSz.Height()-pData->aSz.Height()) / 2;
    1864       10859 :                 DrawTextFlags   nTextStyle   = DrawTextFlags::NONE;
    1865       10859 :                 DrawSymbolFlags nSymbolStyle = DrawSymbolFlags::NONE;
    1866       10859 :                 DrawImageFlags  nImageStyle  = DrawImageFlags::NONE;
    1867             : 
    1868             :                 // submenus without items are not disabled when no items are
    1869             :                 // contained. The application itself should check for this!
    1870             :                 // Otherwise it could happen entries are disabled due to
    1871             :                 // asynchronous loading
    1872       10859 :                 if (!pData->bEnabled)
    1873             :                 {
    1874          63 :                     nTextStyle   |= DrawTextFlags::Disable;
    1875          63 :                     nSymbolStyle |= DrawSymbolFlags::Disable;
    1876          63 :                     nImageStyle  |= DrawImageFlags::Disable;
    1877             :                 }
    1878             : 
    1879             :                 // Separator
    1880       10859 :                 if (!bLayout && !IsMenuBar() && (pData->eType == MenuItemType::SEPARATOR))
    1881             :                 {
    1882          43 :                     bool bNativeOk = false;
    1883          43 :                     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_SEPARATOR))
    1884             :                     {
    1885           0 :                         ControlState nState = ControlState::NONE;
    1886           0 :                         if (pData->bEnabled)
    1887           0 :                             nState |= ControlState::ENABLED;
    1888           0 :                         if (bHighlighted)
    1889           0 :                             nState |= ControlState::SELECTED;
    1890           0 :                         Size aSz(pData->aSz);
    1891           0 :                         aSz.Width() = aOutSz.Width() - 2 * nOuterSpaceX;
    1892           0 :                         Rectangle aItemRect(aPos, aSz);
    1893           0 :                         MenupopupValue aVal(nTextPos - GUTTERBORDER, aItemRect);
    1894             :                         bNativeOk = rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
    1895           0 :                                                                      aItemRect, nState, aVal, OUString());
    1896             :                     }
    1897          43 :                     if (!bNativeOk)
    1898             :                     {
    1899          43 :                         aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height() - 2) / 2);
    1900          43 :                         aTmpPos.X() = aPos.X() + 2 + nOuterSpaceX;
    1901          43 :                         rRenderContext.SetLineColor(rSettings.GetShadowColor());
    1902          43 :                         rRenderContext.DrawLine(aTmpPos, Point(aOutSz.Width() - 3 - 2 * nOuterSpaceX, aTmpPos.Y()));
    1903          43 :                         aTmpPos.Y()++;
    1904          43 :                         rRenderContext.SetLineColor(rSettings.GetLightColor());
    1905          43 :                         rRenderContext.DrawLine(aTmpPos, Point(aOutSz.Width() - 3 - 2 * nOuterSpaceX, aTmpPos.Y()));
    1906          43 :                         rRenderContext.SetLineColor();
    1907             :                     }
    1908             :                 }
    1909             : 
    1910       21718 :                 Rectangle aOuterCheckRect(Point(aPos.X()+nImgOrChkPos, aPos.Y()),
    1911       32577 :                                           Size(pData->aSz.Height(), pData->aSz.Height()));
    1912       10859 :                 aOuterCheckRect.Left() += 1;
    1913       10859 :                 aOuterCheckRect.Right() -= 1;
    1914       10859 :                 aOuterCheckRect.Top() += 1;
    1915       10859 :                 aOuterCheckRect.Bottom() -= 1;
    1916             : 
    1917             :                 // CheckMark
    1918       10859 :                 if (!bLayout && !IsMenuBar() && pData->HasCheck())
    1919             :                 {
    1920             :                     // draw selection transparent marker if checked
    1921             :                     // onto that either a checkmark or the item image
    1922             :                     // will be painted
    1923             :                     // however do not do this if native checks will be painted since
    1924             :                     // the selection color too often does not fit the theme's check and/or radio
    1925             : 
    1926          60 :                     if( !((pData->eType == MenuItemType::IMAGE) || (pData->eType == MenuItemType::STRINGIMAGE)))
    1927             :                     {
    1928          42 :                         if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP,
    1929          42 :                                                                     (pData->nBits & MenuItemBits::RADIOCHECK)
    1930             :                                                                         ? PART_MENU_ITEM_CHECK_MARK
    1931          21 :                                                                         : PART_MENU_ITEM_RADIO_MARK))
    1932             :                         {
    1933           0 :                             ControlPart nPart = ((pData->nBits & MenuItemBits::RADIOCHECK)
    1934             :                                                  ? PART_MENU_ITEM_RADIO_MARK
    1935           0 :                                                  : PART_MENU_ITEM_CHECK_MARK);
    1936             : 
    1937           0 :                             ControlState nState = ControlState::NONE;
    1938             : 
    1939           0 :                             if (pData->bChecked)
    1940           0 :                                 nState |= ControlState::PRESSED;
    1941             : 
    1942           0 :                             if (pData->bEnabled)
    1943           0 :                                 nState |= ControlState::ENABLED;
    1944             : 
    1945           0 :                             if (bHighlighted)
    1946           0 :                                 nState |= ControlState::SELECTED;
    1947             : 
    1948           0 :                             long nCtrlHeight = (pData->nBits & MenuItemBits::RADIOCHECK) ? nCheckHeight : nRadioHeight;
    1949           0 :                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight) / 2;
    1950           0 :                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight) / 2;
    1951             : 
    1952           0 :                             Rectangle aCheckRect(aTmpPos, Size(nCtrlHeight, nCtrlHeight));
    1953           0 :                             Size aSz(pData->aSz);
    1954           0 :                             aSz.Width() = aOutSz.Width() - 2 * nOuterSpaceX;
    1955           0 :                             Rectangle aItemRect(aPos, aSz);
    1956           0 :                             MenupopupValue aVal(nTextPos - GUTTERBORDER, aItemRect);
    1957             :                             rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, nPart, aCheckRect,
    1958           0 :                                                              nState, aVal, OUString());
    1959             :                         }
    1960          21 :                         else if (pData->bChecked) // by default do nothing for unchecked items
    1961             :                         {
    1962          18 :                             ImplPaintCheckBackground(rRenderContext, *pWindow, aOuterCheckRect, pThisItemOnly && bHighlighted);
    1963             : 
    1964             :                             SymbolType eSymbol;
    1965          18 :                             Size aSymbolSize;
    1966          18 :                             if (pData->nBits & MenuItemBits::RADIOCHECK)
    1967             :                             {
    1968           3 :                                 eSymbol = SymbolType::RADIOCHECKMARK;
    1969           3 :                                 aSymbolSize = Size(nFontHeight / 2, nFontHeight / 2);
    1970             :                             }
    1971             :                             else
    1972             :                             {
    1973          15 :                                 eSymbol = SymbolType::CHECKMARK;
    1974          15 :                                 aSymbolSize = Size((nFontHeight * 25) / 40, nFontHeight / 2);
    1975             :                             }
    1976          18 :                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width()) / 2;
    1977          18 :                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height()) / 2;
    1978          18 :                             Rectangle aRect(aTmpPos, aSymbolSize);
    1979          18 :                             aDecoView.DrawSymbol(aRect, eSymbol, rRenderContext.GetTextColor(), nSymbolStyle);
    1980             :                         }
    1981             :                     }
    1982             :                 }
    1983             : 
    1984             :                 // Image:
    1985       10859 :                 if (!bLayout && !IsMenuBar() && ((pData->eType == MenuItemType::IMAGE) || (pData->eType == MenuItemType::STRINGIMAGE)))
    1986             :                 {
    1987             :                     // Don't render an image for a check thing
    1988          97 :                     if (pData->bChecked)
    1989           9 :                         ImplPaintCheckBackground(rRenderContext, *pWindow, aOuterCheckRect, pThisItemOnly && bHighlighted);
    1990             : 
    1991          97 :                     Image aImage = pData->aImage;
    1992             : 
    1993          97 :                     sal_Int32 nScaleFactor = rRenderContext.GetDPIScaleFactor();
    1994          97 :                     if (nScaleFactor != 1)
    1995             :                     {
    1996           0 :                         BitmapEx aBitmap = aImage.GetBitmapEx();
    1997           0 :                         aBitmap.Scale(nScaleFactor, nScaleFactor, BmpScaleFlag::Fast);
    1998           0 :                         aImage = Image(aBitmap);
    1999             :                     }
    2000          97 :                     aTmpPos = aOuterCheckRect.TopLeft();
    2001          97 :                     aTmpPos.X() += (aOuterCheckRect.GetWidth() - aImage.GetSizePixel().Width()) / 2;
    2002          97 :                     aTmpPos.Y() += (aOuterCheckRect.GetHeight() - aImage.GetSizePixel().Height()) / 2;
    2003          97 :                     rRenderContext.DrawImage(aTmpPos, aImage, nImageStyle);
    2004             :                 }
    2005             : 
    2006             :                 // Text:
    2007       10859 :                 if ((pData->eType == MenuItemType::STRING ) || (pData->eType == MenuItemType::STRINGIMAGE))
    2008             :                 {
    2009       10810 :                     aTmpPos.X() = aPos.X() + nTextPos;
    2010       10810 :                     aTmpPos.Y() = aPos.Y();
    2011       10810 :                     aTmpPos.Y() += nTextOffsetY;
    2012       10810 :                     DrawTextFlags nStyle = nTextStyle | DrawTextFlags::Mnemonic;
    2013       10810 :                     if (pData->bIsTemporary)
    2014           0 :                         nStyle |= DrawTextFlags::Disable;
    2015       10810 :                     MetricVector* pVector = bLayout ? &mpLayoutData->m_aUnicodeBoundRects : NULL;
    2016       10810 :                     OUString* pDisplayText = bLayout ? &mpLayoutData->m_aDisplayText : NULL;
    2017       10810 :                     if (bLayout)
    2018             :                     {
    2019          31 :                         mpLayoutData->m_aLineIndices.push_back(mpLayoutData->m_aDisplayText.getLength());
    2020          31 :                         mpLayoutData->m_aLineItemIds.push_back(pData->nId);
    2021          31 :                         mpLayoutData->m_aLineItemPositions.push_back(n);
    2022             :                     }
    2023             :                     // #i47946# with NWF painted menus the background is transparent
    2024             :                     // since DrawCtrlText can depend on the background (e.g. for
    2025             :                     // DrawTextFlags::Disable), temporarily set a background which
    2026             :                     // hopefully matches the NWF background since it is read
    2027             :                     // from the system style settings
    2028       10810 :                     bool bSetTmpBackground = !rRenderContext.IsBackground()
    2029       10810 :                                            && rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL);
    2030       10810 :                     if (bSetTmpBackground)
    2031             :                     {
    2032           0 :                         Color aBg = IsMenuBar() ? rRenderContext.GetSettings().GetStyleSettings().GetMenuBarColor()
    2033           0 :                                                 : rRenderContext.GetSettings().GetStyleSettings().GetMenuColor();
    2034           0 :                         rRenderContext.SetBackground(Wallpaper(aBg));
    2035             :                     }
    2036             :                     // how much space is there for the text ?
    2037       10810 :                     long nMaxItemTextWidth = aOutSz.Width() - aTmpPos.X() - nExtra - nOuterSpaceX;
    2038       10810 :                     if (!IsMenuBar() && pData->aAccelKey.GetCode() && !ImplAccelDisabled())
    2039             :                     {
    2040           0 :                         OUString aAccText = pData->aAccelKey.GetName();
    2041           0 :                         nMaxItemTextWidth -= rRenderContext.GetTextWidth(aAccText) + 3 * nExtra;
    2042             :                     }
    2043       10810 :                     if (!IsMenuBar() && pData->pSubMenu)
    2044             :                     {
    2045          41 :                         nMaxItemTextWidth -= nFontHeight - nExtra;
    2046             :                     }
    2047       10810 :                     OUString aItemText(getShortenedString(pData->aText, rRenderContext, nMaxItemTextWidth));
    2048       10810 :                     rRenderContext.DrawCtrlText(aTmpPos, aItemText, 0, aItemText.getLength(), nStyle, pVector, pDisplayText);
    2049       10810 :                     if (bSetTmpBackground)
    2050           0 :                         rRenderContext.SetBackground();
    2051             :                 }
    2052             : 
    2053             :                 // Accel
    2054       10859 :                 if (!bLayout && !IsMenuBar() && pData->aAccelKey.GetCode() && !ImplAccelDisabled())
    2055             :                 {
    2056           0 :                     OUString aAccText = pData->aAccelKey.GetName();
    2057           0 :                     aTmpPos.X() = aOutSz.Width() - rRenderContext.GetTextWidth(aAccText);
    2058           0 :                     aTmpPos.X() -= 4 * nExtra;
    2059             : 
    2060           0 :                     aTmpPos.X() -= nOuterSpaceX;
    2061           0 :                     aTmpPos.Y() = aPos.Y();
    2062           0 :                     aTmpPos.Y() += nTextOffsetY;
    2063           0 :                     rRenderContext.DrawCtrlText(aTmpPos, aAccText, 0, aAccText.getLength(), nTextStyle);
    2064             :                 }
    2065             : 
    2066             :                 // SubMenu?
    2067       10859 :                 if (!bLayout && !IsMenuBar() && pData->pSubMenu)
    2068             :                 {
    2069          37 :                     bool bNativeOk = false;
    2070          37 :                     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_SUBMENU_ARROW))
    2071             :                     {
    2072           0 :                         ControlState nState = ControlState::NONE;
    2073           0 :                         Size aTmpSz(0, 0);
    2074           0 :                         long aSpacing = 0;
    2075             : 
    2076           0 :                         if (!ImplGetNativeSubmenuArrowSize(rRenderContext, aTmpSz, aSpacing))
    2077             :                         {
    2078           0 :                             aTmpSz = Size(nFontHeight, nFontHeight);
    2079           0 :                             aSpacing = nOuterSpaceX;
    2080             :                         }
    2081             : 
    2082           0 :                         if (pData->bEnabled)
    2083           0 :                             nState |= ControlState::ENABLED;
    2084           0 :                         if (bHighlighted)
    2085           0 :                             nState |= ControlState::SELECTED;
    2086             : 
    2087           0 :                         aTmpPos.X() = aOutSz.Width() - aTmpSz.Width() - aSpacing - nOuterSpaceX;
    2088           0 :                         aTmpPos.Y() = aPos.Y() + ( pData->aSz.Height() - aTmpSz.Height() ) / 2;
    2089           0 :                         aTmpPos.Y() += nExtra / 2;
    2090             : 
    2091           0 :                         Rectangle aItemRect(aTmpPos, aTmpSz);
    2092           0 :                         MenupopupValue aVal(nTextPos - GUTTERBORDER, aItemRect);
    2093             :                         bNativeOk = rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_SUBMENU_ARROW,
    2094           0 :                                                                      aItemRect, nState, aVal, OUString());
    2095             :                     }
    2096          37 :                     if (!bNativeOk)
    2097             :                     {
    2098          37 :                         aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpaceX;
    2099          37 :                         aTmpPos.Y() = aPos.Y();
    2100          37 :                         aTmpPos.Y() += nExtra/2;
    2101          37 :                         aTmpPos.Y() += (pData->aSz.Height() / 2) - (nFontHeight / 4);
    2102          37 :                         if (pData->nBits & MenuItemBits::POPUPSELECT)
    2103             :                         {
    2104           0 :                             rRenderContext.SetTextColor(rSettings.GetMenuTextColor());
    2105           0 :                             Point aTmpPos2(aPos);
    2106           0 :                             aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
    2107           0 :                             aDecoView.DrawFrame(Rectangle(aTmpPos2, Size(nFontHeight + nFontHeight / 4,
    2108           0 :                                                                          pData->aSz.Height())),
    2109           0 :                                                 DrawFrameStyle::Group);
    2110             :                         }
    2111             :                         aDecoView.DrawSymbol(Rectangle(aTmpPos, Size(nFontHeight / 2, nFontHeight / 2)),
    2112          37 :                                              SymbolType::SPIN_RIGHT, rRenderContext.GetTextColor(), nSymbolStyle);
    2113             :                     }
    2114             :                 }
    2115             : 
    2116       10859 :                 if (pThisItemOnly && bHighlighted)
    2117             :                 {
    2118             :                     // This restores the normal menu or menu bar text
    2119             :                     // color for when it is no longer highlighted.
    2120           8 :                     if (IsMenuBar())
    2121           8 :                         rRenderContext.SetTextColor(rSettings.GetMenuBarTextColor());
    2122             :                     else
    2123           0 :                         rRenderContext.SetTextColor(rSettings.GetMenuTextColor());
    2124             :                 }
    2125             :             }
    2126       10859 :             if( bLayout )
    2127             :             {
    2128          37 :                 if (!IsMenuBar())
    2129          28 :                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle(aTopLeft, Size(aOutSz.Width(), pData->aSz.Height()));
    2130             :                 else
    2131           9 :                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle(aTopLeft, pData->aSz);
    2132             :             }
    2133             :         }
    2134             : 
    2135       10923 :         if (!IsMenuBar())
    2136         257 :             aTopLeft.Y() += pData->aSz.Height();
    2137             :         else
    2138       10666 :             aTopLeft.X() += pData->aSz.Width();
    2139             :     }
    2140             : 
    2141        1225 :     if (!bLayout && !pThisItemOnly && pLogo)
    2142             :     {
    2143           0 :         Size aLogoSz = pLogo->aBitmap.GetSizePixel();
    2144             : 
    2145           0 :         Rectangle aRect(Point(), Point(aLogoSz.Width() - 1, aOutSz.Height()));
    2146           0 :         if (rRenderContext.GetColorCount() >= 256)
    2147             :         {
    2148           0 :             Gradient aGrad(GradientStyle_LINEAR, pLogo->aStartColor, pLogo->aEndColor);
    2149           0 :             aGrad.SetAngle(1800);
    2150           0 :             aGrad.SetBorder(15);
    2151           0 :             rRenderContext.DrawGradient(aRect, aGrad);
    2152             :         }
    2153             :         else
    2154             :         {
    2155           0 :             rRenderContext.SetFillColor(pLogo->aStartColor);
    2156           0 :             rRenderContext.DrawRect(aRect);
    2157             :         }
    2158             : 
    2159           0 :         Point aLogoPos(0, aOutSz.Height() - aLogoSz.Height());
    2160           0 :         pLogo->aBitmap.Draw(&rRenderContext, aLogoPos);
    2161        1225 :     }
    2162        1225 : }
    2163             : 
    2164          50 : Menu* Menu::ImplGetStartMenu()
    2165             : {
    2166          50 :     Menu* pStart = this;
    2167         108 :     while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
    2168           8 :         pStart = pStart->pStartedFrom;
    2169          50 :     return pStart;
    2170             : }
    2171             : 
    2172          26 : void Menu::ImplCallHighlight(sal_uInt16 nItem)
    2173             : {
    2174          26 :     ImplMenuDelData aDelData( this );
    2175             : 
    2176          26 :     nSelectedId = 0;
    2177          26 :     MenuItemData* pData = pItemList->GetDataFromPos(nItem);
    2178          26 :     if ( pData )
    2179          10 :         nSelectedId = pData->nId;
    2180          26 :     ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT, GetItemPos( GetCurItemId() ) );
    2181             : 
    2182          26 :     if( !aDelData.isDeleted() )
    2183             :     {
    2184          26 :         Highlight();
    2185          26 :         nSelectedId = 0;
    2186          26 :     }
    2187          26 : }
    2188             : 
    2189           0 : IMPL_LINK_NOARG(Menu, ImplCallSelect)
    2190             : {
    2191           0 :     nEventId = 0;
    2192           0 :     Select();
    2193           0 :     return 0;
    2194             : }
    2195             : 
    2196           0 : Menu* Menu::ImplFindSelectMenu()
    2197             : {
    2198           0 :     Menu* pSelMenu = nEventId ? this : NULL;
    2199             : 
    2200           0 :     for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
    2201             :     {
    2202           0 :         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
    2203             : 
    2204           0 :         if ( pData->pSubMenu )
    2205           0 :             pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
    2206             :     }
    2207             : 
    2208           0 :     return pSelMenu;
    2209             : }
    2210             : 
    2211           0 : Menu* Menu::ImplFindMenu( sal_uInt16 nItemId )
    2212             : {
    2213           0 :     Menu* pSelMenu = NULL;
    2214             : 
    2215           0 :     for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
    2216             :     {
    2217           0 :         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
    2218             : 
    2219           0 :         if( pData->nId == nItemId )
    2220           0 :             pSelMenu = this;
    2221           0 :         else if ( pData->pSubMenu )
    2222           0 :             pSelMenu = pData->pSubMenu->ImplFindMenu( nItemId );
    2223             :     }
    2224             : 
    2225           0 :     return pSelMenu;
    2226             : }
    2227             : 
    2228           5 : void Menu::RemoveDisabledEntries( bool bCheckPopups, bool bRemoveEmptyPopups )
    2229             : {
    2230          31 :     for ( sal_uInt16 n = 0; n < GetItemCount(); n++ )
    2231             :     {
    2232          26 :         bool bRemove = false;
    2233          26 :         MenuItemData* pItem = pItemList->GetDataFromPos( n );
    2234          26 :         if ( pItem->eType == MenuItemType::SEPARATOR )
    2235             :         {
    2236           2 :             if ( !n || ( GetItemType( n-1 ) == MenuItemType::SEPARATOR ) )
    2237           0 :                 bRemove = true;
    2238             :         }
    2239             :         else
    2240          24 :             bRemove = !pItem->bEnabled;
    2241             : 
    2242          26 :         if ( bCheckPopups && pItem->pSubMenu )
    2243             :         {
    2244           4 :             pItem->pSubMenu->RemoveDisabledEntries( true );
    2245           4 :             if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
    2246           1 :                 bRemove = true;
    2247             :         }
    2248             : 
    2249          26 :         if ( bRemove )
    2250           4 :             RemoveItem( n-- );
    2251             :     }
    2252             : 
    2253           5 :     if ( GetItemCount() )
    2254             :     {
    2255           4 :         sal_uInt16 nLast = GetItemCount() - 1;
    2256           4 :         MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
    2257           4 :         if ( pItem->eType == MenuItemType::SEPARATOR )
    2258           0 :             RemoveItem( nLast );
    2259             :     }
    2260           5 :     delete mpLayoutData, mpLayoutData = NULL;
    2261           5 : }
    2262             : 
    2263           0 : bool Menu::HasValidEntries( bool bCheckPopups )
    2264             : {
    2265           0 :     bool bValidEntries = false;
    2266           0 :     sal_uInt16 nCount = GetItemCount();
    2267           0 :     for ( sal_uInt16 n = 0; !bValidEntries && ( n < nCount ); n++ )
    2268             :     {
    2269           0 :         MenuItemData* pItem = pItemList->GetDataFromPos( n );
    2270           0 :         if ( pItem->bEnabled && ( pItem->eType != MenuItemType::SEPARATOR ) )
    2271             :         {
    2272           0 :             if ( bCheckPopups && pItem->pSubMenu )
    2273           0 :                 bValidEntries = pItem->pSubMenu->HasValidEntries( true );
    2274             :             else
    2275           0 :                 bValidEntries = true;
    2276             :         }
    2277             :     }
    2278           0 :     return bValidEntries;
    2279             : }
    2280             : 
    2281           0 : sal_uLong Menu::DeactivateMenuBar(sal_uLong nFocusId)
    2282             : {
    2283           0 :     return nFocusId;
    2284             : }
    2285             : 
    2286           0 : void Menu::MenuBarKeyInput(const KeyEvent&)
    2287             : {
    2288           0 : }
    2289             : 
    2290        7721 : void Menu::ImplKillLayoutData() const
    2291             : {
    2292        7721 :     delete mpLayoutData, mpLayoutData = NULL;
    2293        7721 : }
    2294             : 
    2295           2 : void Menu::ImplFillLayoutData() const
    2296             : {
    2297           2 :     if (pWindow && pWindow->IsReallyVisible())
    2298             :     {
    2299           2 :         mpLayoutData = new MenuLayoutData();
    2300           2 :         if (IsMenuBar())
    2301             :         {
    2302           1 :             ImplPaint(*pWindow, 0, 0, 0, false, true); // FIXME
    2303             :         }
    2304             :         else
    2305             :         {
    2306           1 :             MenuFloatingWindow* pFloat = static_cast<MenuFloatingWindow*>(pWindow.get());
    2307           1 :             ImplPaint(*pWindow, pFloat->nScrollerHeight, pFloat->ImplGetStartY(), 0, false, true); //FIXME
    2308             :         }
    2309             :     }
    2310           2 : }
    2311             : 
    2312           0 : Rectangle Menu::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
    2313             : {
    2314           0 :     long nItemIndex = -1;
    2315           0 :     if( ! mpLayoutData )
    2316           0 :         ImplFillLayoutData();
    2317           0 :     if( mpLayoutData )
    2318             :     {
    2319           0 :         for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
    2320             :         {
    2321           0 :             if( mpLayoutData->m_aLineItemIds[i] == nItemID )
    2322             :             {
    2323           0 :                 nItemIndex = mpLayoutData->m_aLineIndices[i];
    2324           0 :                 break;
    2325             :             }
    2326             :         }
    2327             :     }
    2328           0 :     return (mpLayoutData && nItemIndex != -1) ? mpLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
    2329             : }
    2330             : 
    2331           0 : long Menu::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
    2332             : {
    2333           0 :     long nIndex = -1;
    2334           0 :     rItemID = 0;
    2335           0 :     if( ! mpLayoutData )
    2336           0 :         ImplFillLayoutData();
    2337           0 :     if( mpLayoutData )
    2338             :     {
    2339           0 :         nIndex = mpLayoutData->GetIndexForPoint( rPoint );
    2340           0 :         for( size_t i = 0; i < mpLayoutData->m_aLineIndices.size(); i++ )
    2341             :         {
    2342           0 :             if( mpLayoutData->m_aLineIndices[i] <= nIndex &&
    2343           0 :                 (i == mpLayoutData->m_aLineIndices.size()-1 || mpLayoutData->m_aLineIndices[i+1] > nIndex) )
    2344             :             {
    2345             :                 // make index relative to item
    2346           0 :                 nIndex -= mpLayoutData->m_aLineIndices[i];
    2347           0 :                 rItemID = mpLayoutData->m_aLineItemIds[i];
    2348           0 :                 break;
    2349             :             }
    2350             :         }
    2351             :     }
    2352           0 :     return nIndex;
    2353             : }
    2354             : 
    2355        2616 : Rectangle Menu::GetBoundingRectangle( sal_uInt16 nPos ) const
    2356             : {
    2357        2616 :     Rectangle aRet;
    2358             : 
    2359        2616 :     if (!mpLayoutData )
    2360           2 :         ImplFillLayoutData();
    2361        2616 :     if (mpLayoutData)
    2362             :     {
    2363        2616 :         std::map< sal_uInt16, Rectangle >::const_iterator it = mpLayoutData->m_aVisibleItemBoundRects.find( nPos );
    2364        2616 :         if( it != mpLayoutData->m_aVisibleItemBoundRects.end() )
    2365        2616 :             aRet = it->second;
    2366             :     }
    2367        2616 :     return aRet;
    2368             : }
    2369             : 
    2370           0 : void Menu::SetAccessibleName( sal_uInt16 nItemId, const OUString& rStr )
    2371             : {
    2372             :     size_t nPos;
    2373           0 :     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
    2374             : 
    2375           0 :     if (pData && !rStr.equals(pData->aAccessibleName))
    2376             :     {
    2377           0 :         pData->aAccessibleName = rStr;
    2378           0 :         ImplCallEventListeners(VCLEVENT_MENU_ACCESSIBLENAMECHANGED, nPos);
    2379             :     }
    2380           0 : }
    2381             : 
    2382        2545 : OUString Menu::GetAccessibleName( sal_uInt16 nItemId ) const
    2383             : {
    2384        2545 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2385             : 
    2386        2545 :     if ( pData )
    2387        2545 :         return pData->aAccessibleName;
    2388             : 
    2389           0 :     return OUString();
    2390             : }
    2391             : 
    2392       77956 : void Menu::ImplSetSalMenu( SalMenu *pSalMenu )
    2393             : {
    2394       77956 :     if( mpSalMenu )
    2395          42 :         ImplGetSVData()->mpDefInst->DestroyMenu( mpSalMenu );
    2396       77956 :     mpSalMenu = pSalMenu;
    2397       77956 : }
    2398             : 
    2399           0 : bool Menu::GetSystemMenuData( SystemMenuData* pData ) const
    2400             : {
    2401           0 :     Menu* pMenu = const_cast<Menu*>(this);
    2402           0 :     if( pData && pMenu->ImplGetSalMenu() )
    2403             :     {
    2404           0 :         pMenu->ImplGetSalMenu()->GetSystemMenuData( pData );
    2405           0 :         return true;
    2406             :     }
    2407             :     else
    2408           0 :         return false;
    2409             : }
    2410             : 
    2411        9168 : bool Menu::IsHighlighted( sal_uInt16 nItemPos ) const
    2412             : {
    2413        9168 :     bool bRet = false;
    2414             : 
    2415        9168 :     if( pWindow )
    2416             :     {
    2417         328 :         if (IsMenuBar())
    2418         240 :             bRet = ( nItemPos == static_cast< MenuBarWindow * > (pWindow.get())->GetHighlightedItem() );
    2419             :         else
    2420          88 :             bRet = ( nItemPos == static_cast< MenuFloatingWindow * > (pWindow.get())->GetHighlightedItem() );
    2421             :     }
    2422             : 
    2423        9168 :     return bRet;
    2424             : }
    2425             : 
    2426           0 : void Menu::HighlightItem( sal_uInt16 nItemPos )
    2427             : {
    2428           0 :     if ( pWindow )
    2429             :     {
    2430           0 :         if (IsMenuBar())
    2431             :         {
    2432           0 :             MenuBarWindow* pMenuWin = static_cast< MenuBarWindow* >( pWindow.get() );
    2433           0 :             pMenuWin->SetAutoPopup( false );
    2434           0 :             pMenuWin->ChangeHighlightItem( nItemPos, false );
    2435             :         }
    2436             :         else
    2437             :         {
    2438           0 :             static_cast< MenuFloatingWindow* >( pWindow.get() )->ChangeHighlightItem( nItemPos, false );
    2439             :         }
    2440             :     }
    2441           0 : }
    2442             : 
    2443             : // - MenuBar -
    2444        6412 : IMenuBarWindow* MenuBar::getMenuBarWindow()
    2445             : {
    2446             :     // so far just a dynamic_cast, hopefully to be turned into something saner
    2447             :     // at some stage
    2448        6412 :     IMenuBarWindow *pWin = dynamic_cast<IMenuBarWindow*>(pWindow.get());
    2449             :     //either there is no window (fdo#87663) or it is an IMenuBarWindow
    2450             :     assert(!pWindow || pWin);
    2451        6412 :     return pWin;
    2452             : }
    2453             : 
    2454        3199 : MenuBar::MenuBar()
    2455             :     : Menu(),
    2456             :       mbCloseBtnVisible(false),
    2457             :       mbFloatBtnVisible(false),
    2458             :       mbHideBtnVisible(false),
    2459        3199 :       mbDisplayable(true)
    2460             : {
    2461        3199 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(true, this);
    2462        3199 : }
    2463             : 
    2464           0 : MenuBar::MenuBar( const MenuBar& rMenu )
    2465             :     : Menu(),
    2466             :       mbCloseBtnVisible(false),
    2467             :       mbFloatBtnVisible(false),
    2468             :       mbHideBtnVisible(false),
    2469           0 :       mbDisplayable(true)
    2470             : {
    2471           0 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(true, this);
    2472           0 :     *this = rMenu;
    2473           0 : }
    2474             : 
    2475        9576 : MenuBar::~MenuBar()
    2476             : {
    2477        3192 :     ImplDestroy( this, true );
    2478        6384 : }
    2479             : 
    2480           0 : void MenuBar::ClosePopup(Menu *pMenu)
    2481             : {
    2482           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2483           0 :     if (!pMenuWin)
    2484           0 :         return;
    2485           0 :     pMenuWin->PopupClosed(pMenu);
    2486             : }
    2487             : 
    2488           0 : sal_uLong MenuBar::DeactivateMenuBar(sal_uLong nFocusId)
    2489             : {
    2490           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2491           0 :     nFocusId = pMenuWin ? pMenuWin->GetFocusId() : 0;
    2492           0 :     if (nFocusId)
    2493             :     {
    2494           0 :         pMenuWin->SetFocusId(0);
    2495           0 :         ImplGetSVData()->maWinData.mbNoDeactivate = false;
    2496             :     }
    2497             : 
    2498           0 :     return nFocusId;
    2499             : }
    2500             : 
    2501           0 : void MenuBar::MenuBarKeyInput(const KeyEvent& rEvent)
    2502             : {
    2503           0 :     pWindow->KeyInput(rEvent);
    2504           0 : }
    2505             : 
    2506        4083 : void MenuBar::ShowCloseButton(bool bShow)
    2507             : {
    2508        4083 :     ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
    2509        4083 : }
    2510             : 
    2511        4083 : void MenuBar::ShowButtons( bool bClose, bool bFloat, bool bHide )
    2512             : {
    2513        4955 :     if ((bClose != mbCloseBtnVisible) ||
    2514        1744 :         (bFloat != mbFloatBtnVisible) ||
    2515         872 :         (bHide  != mbHideBtnVisible))
    2516             :     {
    2517        3211 :         mbCloseBtnVisible = bClose;
    2518        3211 :         mbFloatBtnVisible = bFloat;
    2519        3211 :         mbHideBtnVisible = bHide;
    2520        3211 :         IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2521        3211 :         if (pMenuWin)
    2522        3211 :             pMenuWin->ShowButtons(bClose, bFloat, bHide);
    2523             :     }
    2524        4083 : }
    2525             : 
    2526        3197 : void MenuBar::SetDisplayable( bool bDisplayable )
    2527             : {
    2528        3197 :     if( bDisplayable != mbDisplayable )
    2529             :     {
    2530           0 :         mbDisplayable = bDisplayable;
    2531           0 :         IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2532           0 :         if (pMenuWin)
    2533           0 :             pMenuWin->LayoutChanged();
    2534             :     }
    2535        3197 : }
    2536             : 
    2537        3200 : vcl::Window* MenuBar::ImplCreate(vcl::Window* pParent, vcl::Window* pWindow, MenuBar* pMenu, const css::uno::Reference<css::frame::XFrame> &/*rFrame*/)
    2538             : {
    2539        3200 :     MenuBarWindow *pMenuBarWindow = dynamic_cast<MenuBarWindow*>(pWindow);
    2540        3200 :     if (!pMenuBarWindow)
    2541             :     {
    2542        3199 :         pWindow = pMenuBarWindow = VclPtr<MenuBarWindow>::Create( pParent );
    2543             :     }
    2544             : 
    2545        3200 :     pMenu->pStartedFrom = 0;
    2546        3200 :     pMenu->pWindow = pWindow;
    2547        3200 :     pMenuBarWindow->SetMenu(pMenu);
    2548        3200 :     long nHeight = pWindow ? pMenu->ImplCalcSize(pWindow).Height() : 0;
    2549             : 
    2550             :     // depending on the native implementation or the displayable flag
    2551             :     // the menubar windows is suppressed (ie, height=0)
    2552        3200 :     if (!pMenu->IsDisplayable() || (pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar()))
    2553             :     {
    2554           0 :         nHeight = 0;
    2555             :     }
    2556             : 
    2557        3200 :     pMenuBarWindow->SetHeight(nHeight);
    2558        3200 :     return pWindow;
    2559             : }
    2560             : 
    2561        6386 : void MenuBar::ImplDestroy( MenuBar* pMenu, bool bDelete )
    2562             : {
    2563        6386 :     vcl::Window *pWindow = pMenu->ImplGetWindow();
    2564        6386 :     if (pWindow && bDelete)
    2565             :     {
    2566        3193 :         IMenuBarWindow* pMenuWin = pMenu->getMenuBarWindow();
    2567        3193 :         if (pMenuWin)
    2568        3193 :             pMenuWin->KillActivePopup();
    2569        3193 :         pWindow->disposeOnce();
    2570             :     }
    2571        6386 :     pMenu->pWindow = NULL;
    2572        6386 : }
    2573             : 
    2574           0 : bool MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
    2575             : {
    2576           0 :     bool bDone = false;
    2577             : 
    2578             :     // No keyboard processing when system handles the menu or our menubar is invisible
    2579           0 :     if( !IsDisplayable() ||
    2580           0 :         ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
    2581           0 :         return bDone;
    2582             : 
    2583             :     // check for enabled, if this method is called from another window...
    2584           0 :     vcl::Window* pWin = ImplGetWindow();
    2585           0 :     if (pWin && pWin->IsEnabled() && pWin->IsInputEnabled()  && !pWin->IsInModalMode())
    2586             :     {
    2587           0 :         IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2588           0 :         bDone = pMenuWin && pMenuWin->HandleKeyEvent(rKEvent, bFromMenu);
    2589             :     }
    2590           0 :     return bDone;
    2591             : }
    2592             : 
    2593           8 : void MenuBar::SelectItem(sal_uInt16 nId)
    2594             : {
    2595           8 :     if (pWindow)
    2596             :     {
    2597           8 :         pWindow->GrabFocus();
    2598           8 :         nId = GetItemPos( nId );
    2599             : 
    2600           8 :         IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2601           8 :         if (pMenuWin)
    2602             :         {
    2603             :             // #99705# popup the selected menu
    2604           8 :             pMenuWin->SetAutoPopup( true );
    2605           8 :             if (ITEMPOS_INVALID != pMenuWin->GetHighlightedItem())
    2606             :             {
    2607           8 :                 pMenuWin->KillActivePopup();
    2608           8 :                 pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, false );
    2609             :             }
    2610           8 :             if (nId != ITEMPOS_INVALID)
    2611           8 :                 pMenuWin->ChangeHighlightItem( nId, false );
    2612             :         }
    2613             :     }
    2614           8 : }
    2615             : 
    2616             : // handler for native menu selection and command events
    2617             : 
    2618           0 : bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
    2619             : {
    2620           0 :     if( pMenu )
    2621             :     {
    2622           0 :         ImplMenuDelData aDelData( this );
    2623             : 
    2624           0 :         pMenu->pStartedFrom = const_cast<MenuBar*>(this);
    2625           0 :         pMenu->bInCallback = true;
    2626           0 :         pMenu->Activate();
    2627             : 
    2628           0 :         if( !aDelData.isDeleted() )
    2629           0 :             pMenu->bInCallback = false;
    2630             :     }
    2631           0 :     return true;
    2632             : }
    2633             : 
    2634           0 : bool MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
    2635             : {
    2636           0 :     if( pMenu )
    2637             :     {
    2638           0 :         ImplMenuDelData aDelData( this );
    2639             : 
    2640           0 :         pMenu->pStartedFrom = const_cast<MenuBar*>(this);
    2641           0 :         pMenu->bInCallback = true;
    2642           0 :         pMenu->Deactivate();
    2643           0 :         if( !aDelData.isDeleted() )
    2644           0 :             pMenu->bInCallback = false;
    2645             :     }
    2646           0 :     return true;
    2647             : }
    2648             : 
    2649           0 : bool MenuBar::HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nHighlightEventId ) const
    2650             : {
    2651           0 :     if( !pMenu )
    2652           0 :         pMenu = const_cast<MenuBar*>(this)->ImplFindMenu(nHighlightEventId);
    2653           0 :     if( pMenu )
    2654             :     {
    2655           0 :         ImplMenuDelData aDelData( pMenu );
    2656             : 
    2657           0 :         if( mnHighlightedItemPos != ITEMPOS_INVALID )
    2658           0 :             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, mnHighlightedItemPos );
    2659             : 
    2660           0 :         if( !aDelData.isDeleted() )
    2661             :         {
    2662           0 :             pMenu->mnHighlightedItemPos = pMenu->GetItemPos( nHighlightEventId );
    2663           0 :             pMenu->nSelectedId = nHighlightEventId;
    2664           0 :             pMenu->pStartedFrom = const_cast<MenuBar*>(this);
    2665           0 :             pMenu->ImplCallHighlight( pMenu->mnHighlightedItemPos );
    2666             :         }
    2667           0 :         return true;
    2668             :     }
    2669             :     else
    2670           0 :         return false;
    2671             : }
    2672             : 
    2673           0 : bool MenuBar::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
    2674             : {
    2675           0 :     if( !pMenu )
    2676           0 :         pMenu = const_cast<MenuBar*>(this)->ImplFindMenu(nCommandEventId);
    2677           0 :     if( pMenu )
    2678             :     {
    2679           0 :         pMenu->nSelectedId = nCommandEventId;
    2680           0 :         pMenu->pStartedFrom = const_cast<MenuBar*>(this);
    2681           0 :         pMenu->ImplSelect();
    2682           0 :         return true;
    2683             :     }
    2684             :     else
    2685           0 :         return false;
    2686             : }
    2687             : 
    2688           0 : sal_uInt16 MenuBar::AddMenuBarButton( const Image& i_rImage, const Link<>& i_rLink, const OUString& i_rToolTip, sal_uInt16 i_nPos )
    2689             : {
    2690           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2691           0 :     return pMenuWin ? pMenuWin->AddMenuBarButton(i_rImage, i_rLink, i_rToolTip, i_nPos) : 0;
    2692             : }
    2693             : 
    2694           0 : void MenuBar::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link<>& rLink )
    2695             : {
    2696           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2697           0 :     if (!pMenuWin)
    2698           0 :         return;
    2699           0 :     pMenuWin->SetMenuBarButtonHighlightHdl(nId, rLink);
    2700             : }
    2701             : 
    2702           0 : Rectangle MenuBar::GetMenuBarButtonRectPixel( sal_uInt16 nId )
    2703             : {
    2704           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2705           0 :     return pMenuWin ? pMenuWin->GetMenuBarButtonRectPixel(nId) : Rectangle();
    2706             : }
    2707             : 
    2708           0 : void MenuBar::RemoveMenuBarButton( sal_uInt16 nId )
    2709             : {
    2710           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2711           0 :     if (!pMenuWin)
    2712           0 :         return;
    2713           0 :     pMenuWin->RemoveMenuBarButton(nId);
    2714             : }
    2715             : 
    2716           0 : bool MenuBar::HandleMenuButtonEvent( Menu *, sal_uInt16 i_nButtonId )
    2717             : {
    2718           0 :     IMenuBarWindow* pMenuWin = getMenuBarWindow();
    2719           0 :     return pMenuWin && pMenuWin->HandleMenuButtonEvent(i_nButtonId);
    2720             : }
    2721             : 
    2722             : // bool PopupMenu::bAnyPopupInExecute = false;
    2723             : 
    2724          32 : MenuFloatingWindow * PopupMenu::ImplGetFloatingWindow() const {
    2725          32 :     return static_cast<MenuFloatingWindow *>(Menu::ImplGetWindow());
    2726             : }
    2727             : 
    2728       73134 : PopupMenu::PopupMenu()
    2729       73134 :     : pRefAutoSubMenu(NULL)
    2730             : {
    2731       73134 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(false, this);
    2732       73134 : }
    2733             : 
    2734        1655 : PopupMenu::PopupMenu( const ResId& rResId )
    2735        1655 :     : pRefAutoSubMenu(NULL)
    2736             : {
    2737        1655 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(false, this);
    2738             : 
    2739        1655 :     ResMgr* pMgr = rResId.GetResMgr();
    2740        1655 :     if( ! pMgr )
    2741        1655 :         return;
    2742             : 
    2743        1655 :     rResId.SetRT( RSC_MENU );
    2744        1655 :     GetRes( rResId );
    2745             : 
    2746        1655 :     sal_uLong nObjMask = ReadLongRes();
    2747             : 
    2748        1655 :     if( nObjMask & RSC_MENU_ITEMS )
    2749             :     {
    2750        1651 :         sal_uLong nObjFollows = ReadLongRes();
    2751             :         // insert menu items
    2752        6897 :         for( sal_uLong i = 0; i < nObjFollows; i++ )
    2753             :         {
    2754        5246 :             InsertItem( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *pMgr ) );
    2755        5246 :             IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
    2756             :         }
    2757             :     }
    2758             : 
    2759        1655 :     if( nObjMask & RSC_MENU_TEXT )
    2760             :     {
    2761           0 :         aTitleText = ReadStringRes();
    2762             :     }
    2763        1655 :     if( nObjMask & RSC_MENU_DEFAULTITEMID )
    2764           0 :         SetDefaultItem( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
    2765             : }
    2766             : 
    2767           0 : PopupMenu::PopupMenu( const PopupMenu& rMenu )
    2768             :     : Menu(),
    2769           0 :       pRefAutoSubMenu(NULL)
    2770             : {
    2771           0 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu(false, this);
    2772           0 :     *this = rMenu;
    2773           0 : }
    2774             : 
    2775      222393 : PopupMenu::~PopupMenu()
    2776             : {
    2777       74764 :     if( pRefAutoSubMenu && *pRefAutoSubMenu == this )
    2778           0 :         *pRefAutoSubMenu = NULL;    // #111060# avoid second delete in ~MenuItemData
    2779      147629 : }
    2780             : 
    2781           0 : void PopupMenu::ClosePopup(Menu* pMenu)
    2782             : {
    2783           0 :     MenuFloatingWindow* p = dynamic_cast<MenuFloatingWindow*>(ImplGetWindow());
    2784           0 :     PopupMenu *pPopup = dynamic_cast<PopupMenu*>(pMenu);
    2785           0 :     if (p && pMenu)
    2786           0 :         p->KillActivePopup(pPopup);
    2787           0 : }
    2788             : 
    2789           0 : bool PopupMenu::IsInExecute()
    2790             : {
    2791           0 :     return GetActivePopupMenu() != nullptr;
    2792             : }
    2793             : 
    2794           0 : PopupMenu* PopupMenu::GetActivePopupMenu()
    2795             : {
    2796           0 :     ImplSVData* pSVData = ImplGetSVData();
    2797           0 :     return pSVData->maAppData.mpActivePopupMenu;
    2798             : }
    2799             : 
    2800           0 : void PopupMenu::EndExecute( sal_uInt16 nSelectId )
    2801             : {
    2802           0 :     if ( ImplGetWindow() )
    2803           0 :         ImplGetFloatingWindow()->EndExecute( nSelectId );
    2804           0 : }
    2805             : 
    2806           0 : void PopupMenu::SelectItem(sal_uInt16 nId)
    2807             : {
    2808           0 :     if ( ImplGetWindow() )
    2809             :     {
    2810           0 :         if( nId != ITEMPOS_INVALID )
    2811             :         {
    2812           0 :             size_t nPos = 0;
    2813           0 :             MenuItemData* pData = GetItemList()->GetData( nId, nPos );
    2814           0 :             if (pData && pData->pSubMenu)
    2815           0 :                 ImplGetFloatingWindow()->ChangeHighlightItem( nPos, true );
    2816             :             else
    2817           0 :                 ImplGetFloatingWindow()->EndExecute( nId );
    2818             :         }
    2819             :         else
    2820             :         {
    2821           0 :             MenuFloatingWindow* pFloat = ImplGetFloatingWindow();
    2822           0 :             pFloat->GrabFocus();
    2823             : 
    2824           0 :             for( size_t nPos = 0; nPos < GetItemList()->size(); nPos++ )
    2825             :             {
    2826           0 :                 MenuItemData* pData = GetItemList()->GetDataFromPos( nPos );
    2827           0 :                 if( pData->pSubMenu )
    2828             :                 {
    2829           0 :                     pFloat->KillActivePopup();
    2830             :                 }
    2831             :             }
    2832           0 :             pFloat->ChangeHighlightItem( ITEMPOS_INVALID, false );
    2833             :         }
    2834             :     }
    2835           0 : }
    2836             : 
    2837           0 : void PopupMenu::SetSelectedEntry( sal_uInt16 nId )
    2838             : {
    2839           0 :     nSelectedId = nId;
    2840           0 : }
    2841             : 
    2842           0 : sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, const Point& rPopupPos )
    2843             : {
    2844           0 :     return Execute( pExecWindow, Rectangle( rPopupPos, rPopupPos ), PopupMenuFlags::ExecuteDown );
    2845             : }
    2846             : 
    2847           0 : sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, const Rectangle& rRect, PopupMenuFlags nFlags )
    2848             : {
    2849           0 :     ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL window!", 0 );
    2850             : 
    2851           0 :     FloatWinPopupFlags nPopupModeFlags = FloatWinPopupFlags::NONE;
    2852           0 :     if ( nFlags & PopupMenuFlags::ExecuteDown )
    2853           0 :         nPopupModeFlags = FloatWinPopupFlags::Down;
    2854           0 :     else if ( nFlags & PopupMenuFlags::ExecuteUp )
    2855           0 :         nPopupModeFlags = FloatWinPopupFlags::Up;
    2856           0 :     else if ( nFlags & PopupMenuFlags::ExecuteLeft )
    2857           0 :         nPopupModeFlags = FloatWinPopupFlags::Left;
    2858           0 :     else if ( nFlags & PopupMenuFlags::ExecuteRight )
    2859           0 :         nPopupModeFlags = FloatWinPopupFlags::Right;
    2860             :     else
    2861           0 :         nPopupModeFlags = FloatWinPopupFlags::Down;
    2862             : 
    2863           0 :     if (nFlags & PopupMenuFlags::NoMouseUpClose )                      // allow popup menus to stay open on mouse button up
    2864           0 :         nPopupModeFlags |= FloatWinPopupFlags::NoMouseUpClose;    // useful if the menu was opened on mousebutton down (eg toolbox configuration)
    2865             : 
    2866           0 :     if (nFlags & PopupMenuFlags::NoHorzPlacement)
    2867           0 :         nPopupModeFlags |= FloatWinPopupFlags::NoHorzPlacement;
    2868             : 
    2869           0 :     return ImplExecute( pExecWindow, rRect, nPopupModeFlags, 0, false );
    2870             : }
    2871             : 
    2872           8 : sal_uInt16 PopupMenu::ImplExecute( vcl::Window* pW, const Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, bool bPreSelectFirst )
    2873             : {
    2874           8 :     if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
    2875           0 :         return 0;
    2876             : 
    2877           8 :     delete mpLayoutData, mpLayoutData = NULL;
    2878             : 
    2879           8 :     ImplSVData* pSVData = ImplGetSVData();
    2880             : 
    2881           8 :     pStartedFrom = pSFrom;
    2882           8 :     nSelectedId = 0;
    2883           8 :     bCanceled = false;
    2884             : 
    2885           8 :     sal_uLong nFocusId = 0;
    2886           8 :     bool bRealExecute = false;
    2887           8 :     if ( !pStartedFrom )
    2888             :     {
    2889           0 :         pSVData->maWinData.mbNoDeactivate = true;
    2890           0 :         nFocusId = Window::SaveFocus();
    2891           0 :         bRealExecute = true;
    2892             :     }
    2893             :     else
    2894             :     {
    2895             :         // assure that only one menu is open at a time
    2896           8 :         if (pStartedFrom->IsMenuBar() && pSVData->maWinData.mpFirstFloat)
    2897           0 :             pSVData->maWinData.mpFirstFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
    2898             :     }
    2899             : 
    2900             :     DBG_ASSERT( !ImplGetWindow(), "Win?!" );
    2901           8 :     Rectangle aRect( rRect );
    2902           8 :     aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
    2903             : 
    2904           8 :     WinBits nStyle = WB_BORDER;
    2905           8 :     if (bRealExecute)
    2906           0 :         nPopupModeFlags |= FloatWinPopupFlags::NewLevel;
    2907           8 :     nPopupModeFlags |= FloatWinPopupFlags::NoKeyClose | FloatWinPopupFlags::AllMouseButtonClose;
    2908             : 
    2909             :     // could be useful during debugging.
    2910             :     // nPopupModeFlags |= FloatWinPopupFlags::NoFocusClose;
    2911             : 
    2912           8 :     ImplDelData aDelData;
    2913           8 :     pW->ImplAddDel( &aDelData );
    2914             : 
    2915           8 :     bInCallback = true; // set it here, if Activate overridden
    2916           8 :     Activate();
    2917           8 :     bInCallback = false;
    2918             : 
    2919           8 :     if ( aDelData.IsDead() )
    2920           0 :         return 0;   // Error
    2921             : 
    2922           8 :     pW->ImplRemoveDel( &aDelData );
    2923             : 
    2924           8 :     if ( bCanceled || bKilled )
    2925           0 :         return 0;
    2926             : 
    2927           8 :     if ( !GetItemCount() )
    2928           0 :         return 0;
    2929             : 
    2930             :     // The flag MenuFlags::HideDisabledEntries is inherited.
    2931           8 :     if ( pSFrom )
    2932             :     {
    2933           8 :         if ( pSFrom->nMenuFlags & MenuFlags::HideDisabledEntries )
    2934           0 :             nMenuFlags |= MenuFlags::HideDisabledEntries;
    2935             :         else
    2936           8 :             nMenuFlags &= ~MenuFlags::HideDisabledEntries;
    2937             :     }
    2938             :     else
    2939             :         // #102790# context menus shall never show disabled entries
    2940           0 :         nMenuFlags |= MenuFlags::HideDisabledEntries;
    2941             : 
    2942           8 :     sal_uInt16 nVisibleEntries = ImplGetVisibleItemCount();
    2943           8 :     if ( !nVisibleEntries )
    2944             :     {
    2945           0 :         ResMgr* pResMgr = ImplGetResMgr();
    2946           0 :         if( pResMgr )
    2947             :         {
    2948           0 :             OUString aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, *pResMgr ) );
    2949             : 
    2950           0 :             MenuItemData* pData = NbcInsertItem(0xFFFF, MenuItemBits::NONE, aTmpEntryText, NULL, 0xFFFF, OString());
    2951           0 :             size_t nPos = 0;
    2952           0 :             pData = pItemList->GetData( pData->nId, nPos );
    2953             :             assert(pData);
    2954           0 :             if (pData)
    2955             :             {
    2956           0 :                 pData->bIsTemporary = true;
    2957             :             }
    2958           0 :             ImplCallEventListeners(VCLEVENT_MENU_SUBMENUCHANGED, nPos);
    2959             :         }
    2960             :     }
    2961           8 :     else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags & MenuFlags::NoAutoMnemonics ) )
    2962             :     {
    2963           8 :         CreateAutoMnemonics();
    2964             :     }
    2965             : 
    2966          16 :     VclPtrInstance<MenuFloatingWindow> pWin( this, pW, nStyle | WB_SYSTEMWINDOW );
    2967           8 :     if( pSVData->maNWFData.mbFlatMenu )
    2968           0 :         pWin->SetBorderStyle( WindowBorderStyle::NOBORDER );
    2969             :     else
    2970           8 :         pWin->SetBorderStyle( pWin->GetBorderStyle() | WindowBorderStyle::MENU );
    2971           8 :     pWindow = pWin;
    2972             : 
    2973           8 :     Size aSz = ImplCalcSize( pWin );
    2974             : 
    2975           8 :     Rectangle aDesktopRect(pWin->GetDesktopRectPixel());
    2976           8 :     if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
    2977             :     {
    2978           0 :         vcl::Window* pDeskW = pWindow->GetWindow( GetWindowType::RealParent );
    2979           0 :         if( ! pDeskW )
    2980           0 :             pDeskW = pWindow;
    2981           0 :         Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) );
    2982             :         aDesktopRect = Application::GetScreenPosSizePixel(
    2983           0 :             Application::GetBestScreen( Rectangle( aDesktopTL, aRect.GetSize() ) ));
    2984             :     }
    2985             : 
    2986           8 :     long nMaxHeight = aDesktopRect.GetHeight();
    2987             : 
    2988             :     //rhbz#1021915. If a menu won't fit in the desired location the default
    2989             :     //mode is to place it somewhere it will fit.  e.g. above, left, right. For
    2990             :     //some cases, e.g. menubars, it's desirable to limit the options to
    2991             :     //above/below and force the menu to scroll if it won't fit
    2992           8 :     if (nPopupModeFlags & FloatWinPopupFlags::NoHorzPlacement)
    2993             :     {
    2994           8 :         vcl::Window* pRef = pWin;
    2995           8 :         if ( pRef->GetParent() )
    2996           8 :             pRef = pRef->GetParent();
    2997             : 
    2998          16 :         Rectangle devRect(  pRef->OutputToAbsoluteScreenPixel( aRect.TopLeft() ),
    2999          24 :                             pRef->OutputToAbsoluteScreenPixel( aRect.BottomRight() ) );
    3000             : 
    3001           8 :         long nHeightAbove = devRect.Top() - aDesktopRect.Top();
    3002           8 :         long nHeightBelow = aDesktopRect.Bottom() - devRect.Bottom();
    3003           8 :         nMaxHeight = std::min(nMaxHeight, std::max(nHeightAbove, nHeightBelow));
    3004             :     }
    3005             : 
    3006           8 :     if (pStartedFrom && pStartedFrom->IsMenuBar())
    3007           8 :         nMaxHeight -= pW->GetSizePixel().Height();
    3008             :     sal_Int32 nLeft, nTop, nRight, nBottom;
    3009           8 :     pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
    3010           8 :     nMaxHeight -= nTop+nBottom;
    3011           8 :     if ( aSz.Height() > nMaxHeight )
    3012             :     {
    3013           0 :         pWin->EnableScrollMenu( true );
    3014           0 :         sal_uInt16 nStart = ImplGetFirstVisible();
    3015           0 :         sal_uInt16 nEntries = ImplCalcVisEntries( nMaxHeight, nStart );
    3016           0 :         aSz.Height() = ImplCalcHeight( nEntries );
    3017             :     }
    3018             : 
    3019           8 :     pWin->SetFocusId( nFocusId );
    3020           8 :     pWin->SetOutputSizePixel( aSz );
    3021             :     // #102158# menus must never grab the focus, otherwise
    3022             :     // they will be closed immediately
    3023             :     // from now on focus grabbing is only prohibited automatically if
    3024             :     // FloatWinPopupFlags::GrabFocus was set (which is done below), because some
    3025             :     // floaters (like floating toolboxes) may grab the focus
    3026             :     // pWin->GrabFocus();
    3027           8 :     if ( GetItemCount() )
    3028             :     {
    3029           8 :         SalMenu* pMenu = ImplGetSalMenu();
    3030           8 :         if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FloatWinPopupFlags::GrabFocus ) )
    3031             :         {
    3032           0 :             pWin->StopExecute(0);
    3033           0 :             pWin->doShutdown();
    3034           0 :             pWindow->doLazyDelete();
    3035           0 :             pWindow = NULL;
    3036           0 :             return nSelectedId;
    3037             :         }
    3038             :         else
    3039             :         {
    3040           8 :             pWin->StartPopupMode( aRect, nPopupModeFlags | FloatWinPopupFlags::GrabFocus );
    3041             :         }
    3042           8 :         if( pSFrom )
    3043             :         {
    3044             :             sal_uInt16 aPos;
    3045           8 :             if (pSFrom->IsMenuBar())
    3046           8 :                 aPos = static_cast<MenuBarWindow *>(pSFrom->pWindow.get())->GetHighlightedItem();
    3047             :             else
    3048           0 :                 aPos = static_cast<MenuFloatingWindow *>(pSFrom->pWindow.get())->GetHighlightedItem();
    3049             : 
    3050           8 :             pWin->SetPosInParent( aPos );  // store position to be sent in SUBMENUDEACTIVATE
    3051           8 :             pSFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE, aPos );
    3052             :         }
    3053             :     }
    3054           8 :     if ( bPreSelectFirst )
    3055             :     {
    3056           0 :         size_t nCount = pItemList->size();
    3057           0 :         for ( size_t n = 0; n < nCount; n++ )
    3058             :         {
    3059           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3060           0 :             if (  (  pData->bEnabled
    3061           0 :                   || !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus()
    3062             :                   )
    3063           0 :                && ( pData->eType != MenuItemType::SEPARATOR )
    3064           0 :                && ImplIsVisible( n )
    3065           0 :                && ImplIsSelectable( n )
    3066             :                )
    3067             :             {
    3068           0 :                 pWin->ChangeHighlightItem( n, false );
    3069           0 :                 break;
    3070             :             }
    3071             :         }
    3072             :     }
    3073           8 :     if ( bRealExecute )
    3074             :     {
    3075           0 :         pWin->ImplAddDel( &aDelData );
    3076             : 
    3077           0 :         ImplDelData aModalWinDel;
    3078           0 :         pW->ImplAddDel( &aModalWinDel );
    3079           0 :         pW->ImplIncModalCount();
    3080             : 
    3081           0 :         pWin->Execute();
    3082             : 
    3083             :         DBG_ASSERT( ! aModalWinDel.IsDead(), "window for popup died, modal count incorrect !" );
    3084           0 :         if( ! aModalWinDel.IsDead() )
    3085           0 :             pW->ImplDecModalCount();
    3086             : 
    3087           0 :         if ( !aDelData.IsDead() )
    3088           0 :             pWin->ImplRemoveDel( &aDelData );
    3089             :         else
    3090           0 :             return 0;
    3091             : 
    3092             :         // Restore focus (could already have been
    3093             :         // restored in Select)
    3094           0 :         nFocusId = pWin->GetFocusId();
    3095           0 :         if ( nFocusId )
    3096             :         {
    3097           0 :             pWin->SetFocusId( 0 );
    3098           0 :             pSVData->maWinData.mbNoDeactivate = false;
    3099             :         }
    3100           0 :         pWin->ImplEndPopupMode( FloatWinPopupEndFlags::NONE, nFocusId );
    3101             : 
    3102           0 :         if ( nSelectedId )  // then clean up .. ( otherwise done by TH )
    3103             :         {
    3104           0 :             PopupMenu* pSub = pWin->GetActivePopup();
    3105           0 :             while ( pSub )
    3106             :             {
    3107           0 :                 pSub->ImplGetFloatingWindow()->EndPopupMode();
    3108           0 :                 pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
    3109             :             }
    3110             :         }
    3111           0 :         pWin->doShutdown();
    3112           0 :         pWindow->doLazyDelete();
    3113           0 :         pWindow = NULL;
    3114             : 
    3115             :         // is there still Select?
    3116           0 :         Menu* pSelect = ImplFindSelectMenu();
    3117           0 :         if ( pSelect )
    3118             :         {
    3119             :             // Select should be called prior to leaving execute in a popup menu!
    3120           0 :             Application::RemoveUserEvent( pSelect->nEventId );
    3121           0 :             pSelect->nEventId = 0;
    3122           0 :             pSelect->Select();
    3123           0 :         }
    3124             :     }
    3125             : 
    3126          16 :     return bRealExecute ? nSelectedId : 0;
    3127             : }
    3128             : 
    3129           0 : sal_uInt16 PopupMenu::ImplCalcVisEntries( long nMaxHeight, sal_uInt16 nStartEntry, sal_uInt16* pLastVisible ) const
    3130             : {
    3131           0 :     nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
    3132             : 
    3133           0 :     long nHeight = 0;
    3134           0 :     size_t nEntries = pItemList->size();
    3135           0 :     sal_uInt16 nVisEntries = 0;
    3136             : 
    3137           0 :     if ( pLastVisible )
    3138           0 :         *pLastVisible = 0;
    3139             : 
    3140           0 :     for ( size_t n = nStartEntry; n < nEntries; n++ )
    3141             :     {
    3142           0 :         if ( ImplIsVisible( n ) )
    3143             :         {
    3144           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3145           0 :             nHeight += pData->aSz.Height();
    3146           0 :             if ( nHeight > nMaxHeight )
    3147           0 :                 break;
    3148             : 
    3149           0 :             if ( pLastVisible )
    3150           0 :                 *pLastVisible = n;
    3151           0 :             nVisEntries++;
    3152             :         }
    3153             :     }
    3154           0 :     return nVisEntries;
    3155             : }
    3156             : 
    3157           0 : long PopupMenu::ImplCalcHeight( sal_uInt16 nEntries ) const
    3158             : {
    3159           0 :     long nHeight = 0;
    3160             : 
    3161           0 :     sal_uInt16 nFound = 0;
    3162           0 :     for ( size_t n = 0; ( nFound < nEntries ) && ( n < pItemList->size() ); n++ )
    3163             :     {
    3164           0 :         if ( ImplIsVisible( (sal_uInt16) n ) )
    3165             :         {
    3166           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3167           0 :             nHeight += pData->aSz.Height();
    3168           0 :             nFound++;
    3169             :         }
    3170             :     }
    3171             : 
    3172           0 :     nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
    3173             : 
    3174           0 :     return nHeight;
    3175             : }
    3176             : 
    3177      427632 : ImplMenuDelData::ImplMenuDelData( const Menu* pMenu )
    3178             : : mpNext( 0 )
    3179      427632 : , mpMenu( 0 )
    3180             : {
    3181      427632 :     if( pMenu )
    3182      427632 :         const_cast< Menu* >( pMenu )->ImplAddDel( *this );
    3183      427632 : }
    3184             : 
    3185      427632 : ImplMenuDelData::~ImplMenuDelData()
    3186             : {
    3187      427632 :     if( mpMenu )
    3188      427632 :         const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
    3189      427632 : }
    3190             : 
    3191             : namespace vcl { namespace MenuInvalidator {
    3192             :     static VclEventListeners2* pMenuInvalidateListeners = NULL;
    3193         234 :     VclEventListeners2* GetMenuInvalidateListeners()
    3194             :     {
    3195         234 :         if(!pMenuInvalidateListeners)
    3196           3 :             pMenuInvalidateListeners = new VclEventListeners2();
    3197         234 :         return pMenuInvalidateListeners;
    3198             :     }
    3199         232 :     void Invalidated()
    3200             :     {
    3201         232 :         VclSimpleEvent aEvent(0);
    3202         232 :         GetMenuInvalidateListeners()->callListeners(&aEvent);
    3203         232 :     };
    3204             : } }
    3205             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11