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

Generated by: LCOV version 1.10