LCOV - code coverage report
Current view: top level - vcl/source/window - menu.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1464 3193 45.9 %
Date: 2014-04-11 Functions: 156 273 57.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 <com/sun/star/uno/Reference.h>
      53             : #include <com/sun/star/i18n/XCharacterClassification.hpp>
      54             : #include <com/sun/star/lang/XComponent.hpp>
      55             : #include <com/sun/star/accessibility/XAccessible.hpp>
      56             : #include <com/sun/star/accessibility/AccessibleRole.hpp>
      57             : #include <vcl/unowrap.hxx>
      58             : 
      59             : #include <vcl/unohelp.hxx>
      60             : #include <vcl/configsettings.hxx>
      61             : 
      62             : #include "vcl/lazydelete.hxx"
      63             : 
      64             : #include <map>
      65             : #include <vector>
      66             : 
      67             : namespace vcl
      68             : {
      69             : 
      70           4 : struct MenuLayoutData : public ControlLayoutData
      71             : {
      72             :     std::vector< sal_uInt16 >               m_aLineItemIds;
      73             :     std::vector< sal_uInt16 >               m_aLineItemPositions;
      74             :     std::map< sal_uInt16, Rectangle >       m_aVisibleItemBoundRects;
      75             : };
      76             : 
      77             : }
      78             : 
      79             : using namespace ::com::sun::star;
      80             : using namespace vcl;
      81             : 
      82             : #define ITEMPOS_INVALID     0xFFFF
      83             : 
      84             : #define EXTRASPACEY         2
      85             : #define EXTRAITEMHEIGHT     4
      86             : #define GUTTERBORDER        8
      87             : 
      88             : // document closer
      89             : #define IID_DOCUMENTCLOSE 1
      90             : 
      91           0 : static bool ImplAccelDisabled()
      92             : {
      93             :     // display of accelerator strings may be suppressed via configuration
      94             :     static int nAccelDisabled = -1;
      95             : 
      96           0 :     if( nAccelDisabled == -1 )
      97             :     {
      98             :         OUString aStr =
      99             :             vcl::SettingsConfigItem::get()->
     100           0 :             getValue( "Menu", "SuppressAccelerators" );
     101           0 :         nAccelDisabled = aStr.equalsIgnoreAsciiCase("true") ? 1 : 0;
     102             :     }
     103           0 :     return nAccelDisabled == 1;
     104             : }
     105             : 
     106             : struct MenuItemData
     107             : {
     108             :     sal_uInt16      nId;                    // SV Id
     109             :     MenuItemType    eType;                  // MenuItem-Type
     110             :     MenuItemBits    nBits;                  // MenuItem-Bits
     111             :     Menu*           pSubMenu;               // Pointer to SubMenu
     112             :     Menu*           pAutoSubMenu;           // Pointer to SubMenu from Resource
     113             :     OUString        aText;                  // Menu-Text
     114             :     OUString        aHelpText;              // Help-String
     115             :     OUString        aTipHelpText;           // TipHelp-String (eg, expanded filenames)
     116             :     OUString        aCommandStr;            // CommandString
     117             :     OUString        aHelpCommandStr;        // Help command string (to reference external help)
     118             :     OString         sIdent;
     119             :     OString         aHelpId;                // Help-Id
     120             :     sal_uLong           nUserValue;             // User value
     121             :     Image           aImage;                 // Image
     122             :     KeyCode         aAccelKey;              // Accelerator-Key
     123             :     bool            bChecked;               // Checked
     124             :     bool            bEnabled;               // Enabled
     125             :     bool            bVisible;               // Visible (note: this flag will not override MENU_FLAG_HIDEDISABLEDENTRIES when true)
     126             :     bool            bIsTemporary;           // Temporary inserted ('No selection possible')
     127             :     bool            bMirrorMode;
     128             :     long            nItemImageAngle;
     129             :     Size            aSz;                    // only temporarily valid
     130             :     OUString        aAccessibleName;        // accessible name
     131             :     OUString        aAccessibleDescription; // accessible description
     132             : 
     133             :     SalMenuItem*    pSalMenuItem;           // access to native menu
     134             : 
     135       38295 :     MenuItemData()
     136             :         : nId(0)
     137             :         , eType(MENUITEM_DONTKNOW)
     138             :         , nBits(0)
     139             :         , pSubMenu(NULL)
     140             :         , pAutoSubMenu(NULL)
     141             :         , nUserValue(0)
     142             :         , bChecked(false)
     143             :         , bEnabled(false)
     144             :         , bVisible(false)
     145             :         , bIsTemporary(false)
     146             :         , bMirrorMode(false)
     147             :         , nItemImageAngle(0)
     148       38295 :         , pSalMenuItem(NULL)
     149             :     {
     150       38295 :     }
     151      219608 :     MenuItemData( const OUString& rStr, const Image& rImage )
     152             :         : nId(0)
     153             :         , eType(MENUITEM_DONTKNOW)
     154             :         , nBits(0)
     155             :         , pSubMenu(NULL)
     156             :         , pAutoSubMenu(NULL)
     157             :         , aText(rStr)
     158             :         , nUserValue(0)
     159             :         , aImage(rImage)
     160             :         , bChecked(false)
     161             :         , bEnabled(false)
     162             :         , bVisible(false)
     163             :         , bIsTemporary(false)
     164             :         , bMirrorMode(false)
     165             :         , nItemImageAngle(0)
     166      219608 :         , pSalMenuItem(NULL)
     167             :     {
     168      219608 :     }
     169             :     ~MenuItemData();
     170         395 :     bool HasCheck() const
     171             :     {
     172         395 :         return bChecked || ( nBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
     173             :     }
     174             : };
     175             : 
     176      515766 : MenuItemData::~MenuItemData()
     177             : {
     178      257883 :     if( pAutoSubMenu )
     179             :     {
     180           4 :         ((PopupMenu*)pAutoSubMenu)->pRefAutoSubMenu = NULL;
     181           4 :         delete pAutoSubMenu;
     182           4 :         pAutoSubMenu = NULL;
     183             :     }
     184      257883 :     if( pSalMenuItem )
     185           0 :         ImplGetSVData()->mpDefInst->DestroyMenuItem( pSalMenuItem );
     186      257883 : }
     187             : 
     188             : class MenuItemList
     189             : {
     190             : private:
     191             :     typedef ::std::vector< MenuItemData* > MenuItemDataList_impl;
     192             :     MenuItemDataList_impl maItemList;
     193             : 
     194             :     uno::Reference< i18n::XCharacterClassification > xCharClass;
     195             : 
     196             : public:
     197       47123 :                     MenuItemList() {}
     198             :                     ~MenuItemList();
     199             : 
     200             :     MenuItemData*   Insert(
     201             :                         sal_uInt16 nId,
     202             :                         MenuItemType eType,
     203             :                         MenuItemBits nBits,
     204             :                         const OUString& rStr,
     205             :                         const Image& rImage,
     206             :                         Menu* pMenu,
     207             :                         size_t nPos,
     208             :                         const OString &rIdent
     209             :                     );
     210             :     void            InsertSeparator(const OString &rIdent, size_t nPos);
     211             :     void            Remove( size_t nPos );
     212             : 
     213             :     MenuItemData*   GetData( sal_uInt16 nSVId, size_t& rPos ) const;
     214      735229 :     MenuItemData*   GetData( sal_uInt16 nSVId ) const
     215             :                     {
     216             :                         size_t nTemp;
     217      735229 :                         return GetData( nSVId, nTemp );
     218             :                     }
     219      631195 :     MenuItemData*   GetDataFromPos( size_t nPos ) const
     220             :                     {
     221      631195 :                         return ( nPos < maItemList.size() ) ? maItemList[ nPos ] : NULL;
     222             :                     }
     223             : 
     224             :     MenuItemData*   SearchItem(
     225             :                         sal_Unicode cSelectChar,
     226             :                         KeyCode aKeyCode,
     227             :                         sal_uInt16& rPos,
     228             :                         sal_uInt16& nDuplicates,
     229             :                         sal_uInt16 nCurrentPos
     230             :                     ) const;
     231             :     size_t          GetItemCount( sal_Unicode cSelectChar ) const;
     232             :     size_t          GetItemCount( KeyCode aKeyCode ) const;
     233      413836 :     size_t          size()
     234             :                     {
     235      413836 :                         return maItemList.size();
     236             :                     }
     237             : };
     238             : 
     239       94160 : MenuItemList::~MenuItemList()
     240             : {
     241      304902 :     for( size_t i = 0, n = maItemList.size(); i < n; ++i )
     242      257822 :         delete maItemList[ i ];
     243       47080 : }
     244             : 
     245      219608 : MenuItemData* MenuItemList::Insert(
     246             :     sal_uInt16 nId,
     247             :     MenuItemType eType,
     248             :     MenuItemBits nBits,
     249             :     const OUString& rStr,
     250             :     const Image& rImage,
     251             :     Menu* pMenu,
     252             :     size_t nPos,
     253             :     const OString &rIdent
     254             : )
     255             : {
     256      219608 :     MenuItemData* pData     = new MenuItemData( rStr, rImage );
     257      219608 :     pData->nId              = nId;
     258      219608 :     pData->sIdent           = rIdent;
     259      219608 :     pData->eType            = eType;
     260      219608 :     pData->nBits            = nBits;
     261      219608 :     pData->pSubMenu         = NULL;
     262      219608 :     pData->pAutoSubMenu     = NULL;
     263      219608 :     pData->nUserValue       = 0;
     264      219608 :     pData->bChecked         = false;
     265      219608 :     pData->bEnabled         = true;
     266      219608 :     pData->bVisible         = true;
     267      219608 :     pData->bIsTemporary     = false;
     268      219608 :     pData->bMirrorMode      = false;
     269      219608 :     pData->nItemImageAngle  = 0;
     270             : 
     271      219608 :     SalItemParams aSalMIData;
     272      219608 :     aSalMIData.nId = nId;
     273      219608 :     aSalMIData.eType = eType;
     274      219608 :     aSalMIData.nBits = nBits;
     275      219608 :     aSalMIData.pMenu = pMenu;
     276      219608 :     aSalMIData.aText = rStr;
     277      219608 :     aSalMIData.aImage = rImage;
     278             : 
     279             :     // Native-support: returns NULL if not supported
     280      219608 :     pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
     281             : 
     282      219608 :     if( nPos < maItemList.size() ) {
     283           1 :         maItemList.insert( maItemList.begin() + nPos, pData );
     284             :     } else {
     285      219607 :         maItemList.push_back( pData );
     286             :     }
     287      219608 :     return pData;
     288             : }
     289             : 
     290       38295 : void MenuItemList::InsertSeparator(const OString &rIdent, size_t nPos)
     291             : {
     292       38295 :     MenuItemData* pData     = new MenuItemData;
     293       38295 :     pData->nId              = 0;
     294       38295 :     pData->sIdent           = rIdent;
     295       38295 :     pData->eType            = MENUITEM_SEPARATOR;
     296       38295 :     pData->nBits            = 0;
     297       38295 :     pData->pSubMenu         = NULL;
     298       38295 :     pData->pAutoSubMenu     = NULL;
     299       38295 :     pData->nUserValue       = 0;
     300       38295 :     pData->bChecked         = false;
     301       38295 :     pData->bEnabled         = true;
     302       38295 :     pData->bVisible         = true;
     303       38295 :     pData->bIsTemporary     = false;
     304       38295 :     pData->bMirrorMode      = false;
     305       38295 :     pData->nItemImageAngle  = 0;
     306             : 
     307       38295 :     SalItemParams aSalMIData;
     308       38295 :     aSalMIData.nId = 0;
     309       38295 :     aSalMIData.eType = MENUITEM_SEPARATOR;
     310       38295 :     aSalMIData.nBits = 0;
     311       38295 :     aSalMIData.pMenu = NULL;
     312       38295 :     aSalMIData.aText = OUString();
     313       38295 :     aSalMIData.aImage = Image();
     314             : 
     315             :     // Native-support: returns NULL if not supported
     316       38295 :     pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
     317             : 
     318       38295 :     if( nPos < maItemList.size() ) {
     319           0 :         maItemList.insert( maItemList.begin() + nPos, pData );
     320             :     } else {
     321       38295 :         maItemList.push_back( pData );
     322       38295 :     }
     323       38295 : }
     324             : 
     325          61 : void MenuItemList::Remove( size_t nPos )
     326             : {
     327          61 :     if( nPos < maItemList.size() )
     328             :     {
     329          61 :         delete maItemList[ nPos ];
     330          61 :         maItemList.erase( maItemList.begin() + nPos );
     331             :     }
     332          61 : }
     333             : 
     334     1085226 : MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, size_t& rPos ) const
     335             : {
     336     8669658 :     for( size_t i = 0, n = maItemList.size(); i < n; ++i )
     337             :     {
     338     8661505 :         if ( maItemList[ i ]->nId == nSVId )
     339             :         {
     340     1077073 :             rPos = i;
     341     1077073 :             return maItemList[ i ];
     342             :         }
     343             :     }
     344        8153 :     return NULL;
     345             : }
     346             : 
     347           0 : MenuItemData* MenuItemList::SearchItem(
     348             :     sal_Unicode cSelectChar,
     349             :     KeyCode aKeyCode,
     350             :     sal_uInt16& rPos,
     351             :     sal_uInt16& nDuplicates,
     352             :     sal_uInt16 nCurrentPos
     353             : ) const
     354             : {
     355           0 :     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
     356             : 
     357           0 :     size_t nListCount = maItemList.size();
     358             : 
     359             :     // try character code first
     360           0 :     nDuplicates = GetItemCount( cSelectChar );  // return number of duplicates
     361           0 :     if( nDuplicates )
     362             :     {
     363           0 :         for ( rPos = 0; rPos < nListCount; rPos++)
     364             :         {
     365           0 :             MenuItemData* pData = maItemList[ rPos ];
     366           0 :             if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
     367             :             {
     368           0 :                 if( nDuplicates > 1 && rPos == nCurrentPos )
     369           0 :                     continue;   // select next entry with the same mnemonic
     370             :                 else
     371           0 :                     return pData;
     372             :             }
     373             :         }
     374             :     }
     375             : 
     376             :     // nothing found, try keycode instead
     377           0 :     nDuplicates = GetItemCount( aKeyCode ); // return number of duplicates
     378             : 
     379           0 :     if( nDuplicates )
     380             :     {
     381           0 :         char ascii = 0;
     382           0 :         if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
     383           0 :             ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
     384             : 
     385           0 :         for ( rPos = 0; rPos < nListCount; rPos++)
     386             :         {
     387           0 :             MenuItemData* pData = maItemList[ rPos ];
     388           0 :             if ( pData->bEnabled )
     389             :             {
     390           0 :                 sal_Int32 n = pData->aText.indexOf('~');
     391           0 :                 if ( n != -1 )
     392             :                 {
     393           0 :                     KeyCode mnKeyCode;
     394           0 :                     sal_Unicode mnUnicode = pData->aText[n+1];
     395           0 :                     Window* pDefWindow = ImplGetDefaultWindow();
     396           0 :                     if(  (  pDefWindow
     397           0 :                          && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode,
     398           0 :                              Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
     399           0 :                          && aKeyCode.GetCode() == mnKeyCode.GetCode()
     400             :                          )
     401           0 :                       || (  ascii
     402           0 :                          && rI18nHelper.MatchMnemonic( pData->aText, ascii )
     403             :                          )
     404             :                       )
     405             :                     {
     406           0 :                         if( nDuplicates > 1 && rPos == nCurrentPos )
     407           0 :                             continue;   // select next entry with the same mnemonic
     408             :                         else
     409           0 :                             return pData;
     410             :                     }
     411             :                 }
     412             :             }
     413             :         }
     414             :     }
     415             : 
     416           0 :     return NULL;
     417             : }
     418             : 
     419           0 : size_t MenuItemList::GetItemCount( sal_Unicode cSelectChar ) const
     420             : {
     421             :     // returns number of entries with same mnemonic
     422           0 :     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
     423             : 
     424           0 :     size_t nItems = 0;
     425           0 :     for ( size_t nPos = maItemList.size(); nPos; )
     426             :     {
     427           0 :         MenuItemData* pData = maItemList[ --nPos ];
     428           0 :         if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
     429           0 :             nItems++;
     430             :     }
     431             : 
     432           0 :     return nItems;
     433             : }
     434             : 
     435           0 : size_t MenuItemList::GetItemCount( KeyCode aKeyCode ) const
     436             : {
     437             :     // returns number of entries with same mnemonic
     438             :     // uses key codes instead of character codes
     439           0 :     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
     440           0 :     char ascii = 0;
     441           0 :     if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
     442           0 :         ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
     443             : 
     444           0 :     size_t nItems = 0;
     445           0 :     for ( size_t nPos = maItemList.size(); nPos; )
     446             :     {
     447           0 :         MenuItemData* pData = maItemList[ --nPos ];
     448           0 :         if ( pData->bEnabled )
     449             :         {
     450           0 :             sal_Int32 n = pData->aText.indexOf('~');
     451           0 :             if (n != -1)
     452             :             {
     453           0 :                 KeyCode mnKeyCode;
     454             :                 // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
     455             :                 // so we have working shortcuts when ascii mnemonics are used
     456           0 :                 Window* pDefWindow = ImplGetDefaultWindow();
     457           0 :                 if(  (  pDefWindow
     458           0 :                      && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText[n+1],
     459           0 :                          Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
     460           0 :                      && aKeyCode.GetCode() == mnKeyCode.GetCode()
     461             :                      )
     462           0 :                   || (  ascii
     463           0 :                      && rI18nHelper.MatchMnemonic( pData->aText, ascii )
     464             :                      )
     465             :                   )
     466           0 :                     nItems++;
     467             :             }
     468             :         }
     469             :     }
     470             : 
     471           0 :     return nItems;
     472             : }
     473             : 
     474             : // - MenuFloatingWindow -
     475             : 
     476             : class MenuFloatingWindow : public FloatingWindow
     477             : {
     478             :     friend void Menu::ImplFillLayoutData() const;
     479             :     friend Menu::~Menu();
     480             : 
     481             : private:
     482             :     Menu*           pMenu;
     483             :     PopupMenu*      pActivePopup;
     484             :     Timer           aHighlightChangedTimer;
     485             :     Timer           aSubmenuCloseTimer;
     486             :     Timer           aScrollTimer;
     487             :     sal_uLong           nSaveFocusId;
     488             :     sal_uInt16          nHighlightedItem;       // highlighted/selected Item
     489             :     sal_uInt16          nMBDownPos;
     490             :     sal_uInt16          nScrollerHeight;
     491             :     sal_uInt16          nFirstEntry;
     492             :     sal_uInt16          nBorder;
     493             :     sal_uInt16          nPosInParent;
     494             :     bool            bInExecute;
     495             : 
     496             :     bool            bScrollMenu;
     497             :     bool            bScrollUp;
     498             :     bool            bScrollDown;
     499             :     bool            bIgnoreFirstMove;
     500             :     bool            bKeyInput;
     501             : 
     502             :                     DECL_LINK(PopupEnd, void *);
     503             :                     DECL_LINK( HighlightChanged, Timer* );
     504             :                     DECL_LINK(SubmenuClose, void *);
     505             :                     DECL_LINK(AutoScroll, void *);
     506             :                     DECL_LINK( ShowHideListener, VclWindowEvent* );
     507             : 
     508             :     void            StateChanged( StateChangedType nType ) SAL_OVERRIDE;
     509             :     void            DataChanged( const DataChangedEvent& rDCEvt ) SAL_OVERRIDE;
     510             : protected:
     511             :     Region          ImplCalcClipRegion( bool bIncludeLogo = true ) const;
     512             :     void            ImplInitClipRegion();
     513             :     void            ImplDrawScroller( bool bUp );
     514             :     using Window::ImplScroll;
     515             :     void            ImplScroll( const Point& rMousePos );
     516             :     void            ImplScroll( bool bUp );
     517             :     void            ImplCursorUpDown( bool bUp, bool bHomeEnd = false );
     518             :     void            ImplHighlightItem( const MouseEvent& rMEvt, bool bMBDown );
     519             :     long            ImplGetStartY() const;
     520             :     Rectangle       ImplGetItemRect( sal_uInt16 nPos );
     521             : 
     522             : public:
     523             :                     MenuFloatingWindow( Menu* pMenu, Window* pParent, WinBits nStyle );
     524             :                     virtual ~MenuFloatingWindow();
     525             : 
     526             :             void    doShutdown();
     527             : 
     528             :     virtual void    MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     529             :     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     530             :     virtual void    MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     531             :     virtual void    KeyInput( const KeyEvent& rKEvent ) SAL_OVERRIDE;
     532             :     virtual void    Command( const CommandEvent& rCEvt ) SAL_OVERRIDE;
     533             :     virtual void    Paint( const Rectangle& rRect ) SAL_OVERRIDE;
     534             :     virtual void    RequestHelp( const HelpEvent& rHEvt ) SAL_OVERRIDE;
     535             :     virtual void    Resize() SAL_OVERRIDE;
     536             : 
     537           8 :     void            SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
     538           0 :     sal_uLong           GetFocusId() const      { return nSaveFocusId; }
     539             : 
     540             :     void            EnableScrollMenu( bool b );
     541          15 :     bool            IsScrollMenu() const        { return bScrollMenu; }
     542           0 :     sal_uInt16          GetScrollerHeight() const   { return nScrollerHeight; }
     543             : 
     544             :     void            Execute();
     545             :     void            StopExecute( sal_uLong nFocusId = 0 );
     546             :     void            EndExecute();
     547             :     void            EndExecute( sal_uInt16 nSelectId );
     548             : 
     549           0 :     PopupMenu*      GetActivePopup() const  { return pActivePopup; }
     550             :     void            KillActivePopup( PopupMenu* pThisOnly = NULL );
     551             : 
     552             :     void            HighlightItem( sal_uInt16 nPos, bool bHighlight );
     553             :     void            ChangeHighlightItem( sal_uInt16 n, bool bStartPopupTimer );
     554          68 :     sal_uInt16          GetHighlightedItem() const { return nHighlightedItem; }
     555             : 
     556           8 :     void            SetPosInParent( sal_uInt16 nPos ) { nPosInParent = nPos; }
     557             : 
     558             :     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible() SAL_OVERRIDE;
     559             : };
     560             : 
     561             : // To get the transparent mouse-over look, the closer is actually a toolbox
     562             : // overload DataChange to handle style changes correctly
     563        2034 : class DecoToolBox : public ToolBox
     564             : {
     565             :     long lastSize;
     566             :     Size maMinSize;
     567             : 
     568             :     using Window::ImplInit;
     569             : public:
     570             :             DecoToolBox( Window* pParent, WinBits nStyle = 0 );
     571             :     void    ImplInit();
     572             : 
     573             :     void    DataChanged( const DataChangedEvent& rDCEvt ) SAL_OVERRIDE;
     574             : 
     575             :     void    SetImages( long nMaxHeight = 0, bool bForce = false );
     576             : 
     577             :     void    calcMinSize();
     578             :     Size    getMinSize();
     579             : 
     580             :     Image   maImage;
     581             : };
     582             : 
     583        2042 : DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
     584        2042 :     ToolBox( pParent, nStyle )
     585             : {
     586        2042 :     ImplInit();
     587        2042 : }
     588             : 
     589        2042 : void DecoToolBox::ImplInit()
     590             : {
     591        2042 :     lastSize = -1;
     592        2042 :     calcMinSize();
     593        2042 : }
     594             : 
     595           2 : void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
     596             : {
     597           2 :     Window::DataChanged( rDCEvt );
     598             : 
     599           2 :     if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
     600             :     {
     601           0 :         calcMinSize();
     602           0 :         SetBackground();
     603           0 :         SetImages( 0, true);
     604             :     }
     605           2 : }
     606             : 
     607        2042 : void DecoToolBox::calcMinSize()
     608             : {
     609        2042 :     ToolBox aTbx( GetParent() );
     610        2042 :     if( GetItemCount() == 0 )
     611             :     {
     612        2042 :         ResMgr* pResMgr = ImplGetResMgr();
     613             : 
     614        2042 :         Bitmap aBitmap;
     615        2042 :         if( pResMgr )
     616        2042 :             aBitmap = Bitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
     617        2042 :         aTbx.InsertItem( IID_DOCUMENTCLOSE, Image( aBitmap ) );
     618             :     }
     619             :     else
     620             :     {
     621           0 :         sal_uInt16 nItems = GetItemCount();
     622           0 :         for( sal_uInt16 i = 0; i < nItems; i++ )
     623             :         {
     624           0 :             sal_uInt16 nId = GetItemId( i );
     625           0 :             aTbx.InsertItem( nId, GetItemImage( nId ) );
     626             :         }
     627             :     }
     628        2042 :     aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
     629        2042 :     maMinSize = aTbx.CalcWindowSizePixel();
     630        2042 : }
     631             : 
     632        6211 : Size DecoToolBox::getMinSize()
     633             : {
     634        6211 :     return maMinSize;
     635             : }
     636             : 
     637        2000 : void DecoToolBox::SetImages( long nMaxHeight, bool bForce )
     638             : {
     639        2000 :     long border = getMinSize().Height() - maImage.GetSizePixel().Height();
     640             : 
     641        2000 :     if( !nMaxHeight && lastSize != -1 )
     642           0 :         nMaxHeight = lastSize + border; // don't change anything if called with 0
     643             : 
     644        2000 :     if( nMaxHeight < getMinSize().Height() )
     645           0 :         nMaxHeight = getMinSize().Height();
     646             : 
     647        2000 :     if( (lastSize != nMaxHeight - border) || bForce )
     648             :     {
     649        1975 :         lastSize = nMaxHeight - border;
     650             : 
     651        1975 :         Color       aEraseColor( 255, 255, 255, 255 );
     652        1975 :         BitmapEx    aBmpExDst( maImage.GetBitmapEx() );
     653        3950 :         BitmapEx    aBmpExSrc( aBmpExDst );
     654             : 
     655        1975 :         aEraseColor.SetTransparency( 255 );
     656        1975 :         aBmpExDst.Erase( aEraseColor );
     657        1975 :         aBmpExDst.SetSizePixel( Size( lastSize, lastSize ) );
     658             : 
     659        1975 :         Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
     660        3950 :         Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
     661        3950 :                                 (lastSize - maImage.GetSizePixel().Height())/2 ),
     662        7900 :                             maImage.GetSizePixel() );
     663             : 
     664        1975 :         aBmpExDst.CopyPixel( aDestRect, aSrcRect, &aBmpExSrc );
     665        3950 :         SetItemImage( IID_DOCUMENTCLOSE, Image( aBmpExDst ) );
     666             :     }
     667        2000 : }
     668             : 
     669             : // a basic class for both (due to pActivePopup, Timer,...) would be nice,
     670             : // but a container class should have been created then, as they
     671             : // would be derived from different windows
     672             : // In most functions we would have to create exceptions for
     673             : // menubar, popupmenu, hence we made two classes
     674             : 
     675             : class MenuBarWindow : public Window
     676             : {
     677             :     friend class MenuBar;
     678             :     friend class Menu;
     679             : 
     680             : private:
     681             :     struct AddButtonEntry
     682             :     {
     683             :         sal_uInt16      m_nId;
     684             :         Link        m_aSelectLink;
     685             :         Link        m_aHighlightLink;
     686             : 
     687           0 :         AddButtonEntry() : m_nId( 0 ) {}
     688             :     };
     689             : 
     690             :     Menu*           pMenu;
     691             :     PopupMenu*      pActivePopup;
     692             :     sal_uInt16          nHighlightedItem;
     693             :     sal_uInt16          nRolloveredItem;
     694             :     sal_uLong           nSaveFocusId;
     695             :     bool            mbAutoPopup;
     696             :     bool            bIgnoreFirstMove;
     697             :     bool            bStayActive;
     698             : 
     699             :     DecoToolBox     aCloser;
     700             :     PushButton      aFloatBtn;
     701             :     PushButton      aHideBtn;
     702             : 
     703             :     std::map< sal_uInt16, AddButtonEntry > m_aAddButtons;
     704             : 
     705             :     void            HighlightItem( sal_uInt16 nPos, bool bHighlight );
     706             :     void            ChangeHighlightItem( sal_uInt16 n, bool bSelectPopupEntry, bool bAllowRestoreFocus = true, bool bDefaultToDocument = true );
     707             : 
     708             :     sal_uInt16          ImplFindEntry( const Point& rMousePos ) const;
     709             :     void            ImplCreatePopup( bool bPreSelectFirst );
     710             :     bool            ImplHandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu = true );
     711             :     Rectangle       ImplGetItemRect( sal_uInt16 nPos );
     712             : 
     713             :     void            ImplInitStyleSettings();
     714             : 
     715             :                     DECL_LINK(CloserHdl, void *);
     716             :                     DECL_LINK(FloatHdl, void *);
     717             :                     DECL_LINK(HideHdl, void *);
     718             :                     DECL_LINK( ToolboxEventHdl, VclWindowEvent* );
     719             :                     DECL_LINK( ShowHideListener, VclWindowEvent* );
     720             : 
     721             :     void            StateChanged( StateChangedType nType ) SAL_OVERRIDE;
     722             :     void            DataChanged( const DataChangedEvent& rDCEvt ) SAL_OVERRIDE;
     723             :     void            LoseFocus() SAL_OVERRIDE;
     724             :     void            GetFocus() SAL_OVERRIDE;
     725             : 
     726             : public:
     727             :                     MenuBarWindow( Window* pParent );
     728             :                     virtual ~MenuBarWindow();
     729             : 
     730             :     void            ShowButtons( bool bClose, bool bFloat, bool bHide );
     731             : 
     732             :     virtual void    MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     733             :     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     734             :     virtual void    MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
     735             :     virtual void    KeyInput( const KeyEvent& rKEvent ) SAL_OVERRIDE;
     736             :     virtual void    Paint( const Rectangle& rRect ) SAL_OVERRIDE;
     737             :     virtual void    Resize() SAL_OVERRIDE;
     738             :     virtual void    RequestHelp( const HelpEvent& rHEvt ) SAL_OVERRIDE;
     739             : 
     740           0 :     void            SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
     741           0 :     sal_uLong           GetFocusId() const { return nSaveFocusId; }
     742             : 
     743             :     void            SetMenu( MenuBar* pMenu );
     744             :     void            KillActivePopup();
     745             :     void            PopupClosed( Menu* pMenu );
     746         238 :     sal_uInt16          GetHighlightedItem() const { return nHighlightedItem; }
     747             :     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible() SAL_OVERRIDE;
     748             : 
     749           8 :     void SetAutoPopup( bool bAuto ) { mbAutoPopup = bAuto; }
     750             :     void            ImplLayoutChanged();
     751             :     Size            MinCloseButtonSize();
     752             : 
     753             :     // add an arbitrary button to the menubar (will appear next to closer)
     754             :     sal_uInt16              AddMenuBarButton( const Image&, const Link&, const OUString&, sal_uInt16 nPos );
     755             :     void                SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& );
     756             :     Rectangle           GetMenuBarButtonRectPixel( sal_uInt16 nId );
     757             :     void                RemoveMenuBarButton( sal_uInt16 nId );
     758             :     bool                HandleMenuButtonEvent( sal_uInt16 i_nButtonId );
     759             : };
     760             : 
     761           0 : static void ImplAddNWFSeparator( Window *pThis, const MenubarValue& rMenubarValue )
     762             : {
     763             :     // add a separator if
     764             :     // - we have an adjacent docking area
     765             :     // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
     766           0 :     if( rMenubarValue.maTopDockingAreaHeight && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB && !ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
     767             :     {
     768             :         // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
     769             : 
     770           0 :         pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetSeparatorColor() );
     771           0 :         Point aPt;
     772           0 :         Rectangle aRect( aPt, pThis->GetOutputSizePixel() );
     773           0 :         pThis->DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
     774             :     }
     775           0 : }
     776             : 
     777       30387 : static void ImplSetMenuItemData( MenuItemData* pData )
     778             : {
     779             :     // convert data
     780       30387 :     if ( !pData->aImage )
     781        6072 :         pData->eType = MENUITEM_STRING;
     782       24315 :     else if ( pData->aText.isEmpty() )
     783          32 :         pData->eType = MENUITEM_IMAGE;
     784             :     else
     785       24283 :         pData->eType = MENUITEM_STRINGIMAGE;
     786       30387 : }
     787             : 
     788           0 : static sal_uLong ImplChangeTipTimeout( sal_uLong nTimeout, Window *pWindow )
     789             : {
     790           0 :        AllSettings aAllSettings( pWindow->GetSettings() );
     791           0 :        HelpSettings aHelpSettings( aAllSettings.GetHelpSettings() );
     792           0 :        sal_uLong nRet = aHelpSettings.GetTipTimeout();
     793           0 :        aHelpSettings.SetTipTimeout( nTimeout );
     794           0 :        aAllSettings.SetHelpSettings( aHelpSettings );
     795           0 :        pWindow->SetSettings( aAllSettings );
     796           0 :        return nRet;
     797             : }
     798             : 
     799           0 : static bool ImplHandleHelpEvent( Window* pMenuWindow, Menu* pMenu, sal_uInt16 nHighlightedItem, const HelpEvent& rHEvt, const Rectangle &rHighlightRect )
     800             : {
     801           0 :     if( ! pMenu )
     802           0 :         return false;
     803             : 
     804           0 :     bool bDone = false;
     805           0 :     sal_uInt16 nId = 0;
     806             : 
     807           0 :     if ( nHighlightedItem != ITEMPOS_INVALID )
     808             :     {
     809           0 :         MenuItemData* pItemData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
     810           0 :         if ( pItemData )
     811           0 :             nId = pItemData->nId;
     812             :     }
     813             : 
     814           0 :     if ( ( rHEvt.GetMode() & HELPMODE_BALLOON ) && pMenuWindow )
     815             :     {
     816           0 :         Point aPos;
     817           0 :         if( rHEvt.KeyboardActivated() )
     818           0 :             aPos = rHighlightRect.Center();
     819             :         else
     820           0 :             aPos = rHEvt.GetMousePosPixel();
     821             : 
     822           0 :         Rectangle aRect( aPos, Size() );
     823           0 :         if (!pMenu->GetHelpText(nId).isEmpty())
     824           0 :             Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
     825             :         else
     826             :         {
     827             :             // give user a chance to read the full filename
     828           0 :             sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
     829             :             // call always, even when strlen==0 to correctly remove tip
     830           0 :             Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
     831           0 :             ImplChangeTipTimeout( oldTimeout, pMenuWindow );
     832             :         }
     833           0 :         bDone = true;
     834             :     }
     835           0 :     else if ( ( rHEvt.GetMode() & HELPMODE_QUICK ) && pMenuWindow )
     836             :     {
     837           0 :         Point aPos = rHEvt.GetMousePosPixel();
     838           0 :         Rectangle aRect( aPos, Size() );
     839             :         // give user a chance to read the full filename
     840           0 :         sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
     841             :         // call always, even when strlen==0 to correctly remove tip
     842           0 :         Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
     843           0 :         ImplChangeTipTimeout( oldTimeout, pMenuWindow );
     844           0 :         bDone = true;
     845             :     }
     846           0 :     else if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
     847             :     {
     848             :         // is help in the application selected
     849           0 :         Help* pHelp = Application::GetHelp();
     850           0 :         if ( pHelp )
     851             :         {
     852             :             // is an id available, then call help with the id, otherwise
     853             :             // use help-index
     854           0 :             OUString aCommand = pMenu->GetItemCommand( nId );
     855           0 :             OString aHelpId(  pMenu->GetHelpId( nId ) );
     856           0 :             if( aHelpId.isEmpty() )
     857           0 :                 aHelpId = OOO_HELP_INDEX;
     858             : 
     859           0 :             if ( !aCommand.isEmpty() )
     860           0 :                 pHelp->Start( aCommand, NULL );
     861             :             else
     862           0 :                 pHelp->Start( OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
     863             :         }
     864           0 :         bDone = true;
     865             :     }
     866           0 :     return bDone;
     867             : }
     868             : 
     869           0 : static int ImplGetTopDockingAreaHeight( Window *pWindow )
     870             : {
     871             :     // find docking area that is top aligned and return its height
     872             :     // note: dockingareas are direct children of the SystemWindow
     873           0 :     if( pWindow->ImplGetFrameWindow() )
     874             :     {
     875           0 :         Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( WINDOW_FIRSTCHILD ); //mpWindowImpl->mpFirstChild;
     876           0 :         while( pWin )
     877             :         {
     878           0 :             if( pWin->IsSystemWindow() )
     879             :             {
     880           0 :                 Window *pChildWin = pWin->GetWindow( WINDOW_FIRSTCHILD ); //mpWindowImpl->mpFirstChild;
     881           0 :                 while( pChildWin )
     882             :                 {
     883           0 :                     DockingAreaWindow *pDockingArea = NULL;
     884           0 :                     if ( pChildWin->GetType() == WINDOW_DOCKINGAREA )
     885           0 :                         pDockingArea = static_cast< DockingAreaWindow* >( pChildWin );
     886             : 
     887           0 :                     if( pDockingArea && pDockingArea->GetAlign() == WINDOWALIGN_TOP &&
     888           0 :                         pDockingArea->IsVisible() && pDockingArea->GetOutputSizePixel().Height() != 0 )
     889             :                     {
     890           0 :                         return pDockingArea->GetOutputSizePixel().Height();
     891             :                     }
     892             : 
     893           0 :                     pChildWin = pChildWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
     894             :                 }
     895             : 
     896             :             }
     897             : 
     898           0 :             pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
     899             :         }
     900             :     }
     901           0 :     return 0;
     902             : }
     903             : 
     904       45081 : Menu::Menu()
     905             : {
     906       45081 :     bIsMenuBar = false;
     907       45081 :     ImplInit();
     908       45081 : }
     909             : 
     910             : // this constructor makes sure we're creating the native menu
     911             : // with the correct type (ie, MenuBar vs. PopupMenu)
     912        2042 : Menu::Menu( bool bMenubar )
     913             : {
     914        2042 :     bIsMenuBar = bMenubar;
     915        2042 :     ImplInit();
     916        2042 : }
     917             : 
     918       94160 : Menu::~Menu()
     919             : {
     920             : 
     921       47080 :     vcl::LazyDeletor<Menu>::Undelete( this );
     922             : 
     923       47080 :     ImplCallEventListeners( VCLEVENT_OBJECT_DYING, ITEMPOS_INVALID );
     924             : 
     925             :     // at the window free the reference to the accessible component
     926             :     // and make sure the MenuFloatingWindow knows about our destruction
     927       47080 :     if ( pWindow )
     928             :     {
     929           0 :         MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
     930           0 :         if( pFloat->pMenu == this )
     931           0 :             pFloat->pMenu = NULL;
     932           0 :         pWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
     933             :     }
     934             : 
     935             :     // dispose accessible components
     936       47080 :     if ( mxAccessible.is() )
     937             :     {
     938         288 :         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComponent( mxAccessible, ::com::sun::star::uno::UNO_QUERY );
     939         288 :         if ( xComponent.is() )
     940         288 :             xComponent->dispose();
     941             :     }
     942             : 
     943       47080 :     if ( nEventId )
     944           0 :         Application::RemoveUserEvent( nEventId );
     945             : 
     946             :     // Notify deletion of this menu
     947       47080 :     ImplMenuDelData* pDelData = mpFirstDel;
     948       94160 :     while ( pDelData )
     949             :     {
     950           0 :         pDelData->mpMenu = NULL;
     951           0 :         pDelData = pDelData->mpNext;
     952             :     }
     953             : 
     954       47080 :     bKilled = true;
     955             : 
     956       47080 :     delete pItemList;
     957       47080 :     delete pLogo;
     958       47080 :     delete mpLayoutData;
     959             : 
     960             :     // Native-support: destroy SalMenu
     961       47080 :     ImplSetSalMenu( NULL );
     962       47080 : }
     963             : 
     964       47123 : void Menu::ImplInit()
     965             : {
     966       47123 :     mnHighlightedItemPos = ITEMPOS_INVALID;
     967       47123 :     mpSalMenu       = NULL;
     968       47123 :     nMenuFlags      = 0;
     969       47123 :     nDefaultItem    = 0;
     970             :     //bIsMenuBar      = false;  // this is now set in the ctor, must not be changed here!!!
     971       47123 :     nSelectedId     = 0;
     972       47123 :     pItemList       = new MenuItemList;
     973       47123 :     pLogo           = NULL;
     974       47123 :     pStartedFrom    = NULL;
     975       47123 :     pWindow         = NULL;
     976       47123 :     nEventId        = 0;
     977       47123 :     bCanceled       = false;
     978       47123 :     bInCallback     = false;
     979       47123 :     bKilled         = false;
     980       47123 :     mpLayoutData    = NULL;
     981       47123 :     mpFirstDel      = NULL;         // Dtor notification list
     982             :     // Native-support: returns NULL if not supported
     983       47123 :     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu( bIsMenuBar, this );
     984       47123 : }
     985             : 
     986        1011 : void Menu::ImplLoadRes( const ResId& rResId )
     987             : {
     988        1011 :     ResMgr* pMgr = rResId.GetResMgr();
     989        1011 :     if( ! pMgr )
     990        1011 :         return;
     991             : 
     992        1011 :     rResId.SetRT( RSC_MENU );
     993        1011 :     GetRes( rResId );
     994             : 
     995        1011 :     sal_uLong nObjMask = ReadLongRes();
     996             : 
     997        1011 :     if( nObjMask & RSC_MENU_ITEMS )
     998             :     {
     999        1007 :         sal_uLong nObjFollows = ReadLongRes();
    1000             :         // insert menu items
    1001        4869 :         for( sal_uLong i = 0; i < nObjFollows; i++ )
    1002             :         {
    1003        3862 :             InsertItem( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
    1004        3862 :             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
    1005             :         }
    1006             :     }
    1007             : 
    1008        1011 :     if( nObjMask & RSC_MENU_TEXT )
    1009             :     {
    1010           0 :         if( bIsMenuBar ) // no title in menubar
    1011           0 :             ReadStringRes();
    1012             :         else
    1013           0 :             aTitleText = ReadStringRes();
    1014             :     }
    1015        1011 :     if( nObjMask & RSC_MENU_DEFAULTITEMID )
    1016           0 :         SetDefaultItem( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
    1017             : }
    1018             : 
    1019           9 : void Menu::CreateAutoMnemonics()
    1020             : {
    1021           9 :     MnemonicGenerator aMnemonicGenerator;
    1022             :     size_t n;
    1023         226 :     for ( n = 0; n < pItemList->size(); n++ )
    1024             :     {
    1025         217 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
    1026         217 :         if ( ! (pData->nBits & MIB_NOSELECT ) )
    1027         217 :             aMnemonicGenerator.RegisterMnemonic( pData->aText );
    1028             :     }
    1029         226 :     for ( n = 0; n < pItemList->size(); n++ )
    1030             :     {
    1031         217 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
    1032         217 :         if ( ! (pData->nBits & MIB_NOSELECT ) )
    1033         217 :             pData->aText = aMnemonicGenerator.CreateMnemonic( pData->aText );
    1034           9 :     }
    1035           9 : }
    1036             : 
    1037          18 : void Menu::Activate()
    1038             : {
    1039          18 :     bInCallback = true;
    1040             : 
    1041          18 :     ImplMenuDelData aDelData( this );
    1042             : 
    1043          18 :     ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE, ITEMPOS_INVALID );
    1044             : 
    1045          18 :     if( !aDelData.isDeleted() )
    1046             :     {
    1047          18 :         if ( !aActivateHdl.Call( this ) )
    1048             :         {
    1049           0 :             if( !aDelData.isDeleted() )
    1050             :             {
    1051           0 :                 Menu* pStartMenu = ImplGetStartMenu();
    1052           0 :                 if ( pStartMenu && ( pStartMenu != this ) )
    1053             :                 {
    1054           0 :                     pStartMenu->bInCallback = true;
    1055             :                     // MT 11/01: Call EventListener here? I don't know...
    1056           0 :                     pStartMenu->aActivateHdl.Call( this );
    1057           0 :                     pStartMenu->bInCallback = false;
    1058             :                 }
    1059             :             }
    1060             :         }
    1061          18 :         bInCallback = false;
    1062          18 :     }
    1063          18 : }
    1064             : 
    1065          24 : void Menu::Deactivate()
    1066             : {
    1067         400 :     for ( size_t n = pItemList->size(); n; )
    1068             :     {
    1069         352 :         MenuItemData* pData = pItemList->GetDataFromPos( --n );
    1070         352 :         if ( pData->bIsTemporary )
    1071           0 :             pItemList->Remove( n );
    1072             :     }
    1073             : 
    1074          24 :     bInCallback = true;
    1075             : 
    1076          24 :     ImplMenuDelData aDelData( this );
    1077             : 
    1078          24 :     Menu* pStartMenu = ImplGetStartMenu();
    1079          24 :     ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE, ITEMPOS_INVALID );
    1080             : 
    1081          24 :     if( !aDelData.isDeleted() )
    1082             :     {
    1083          24 :         if ( !aDeactivateHdl.Call( this ) )
    1084             :         {
    1085           0 :             if( !aDelData.isDeleted() )
    1086             :             {
    1087           0 :                 if ( pStartMenu && ( pStartMenu != this ) )
    1088             :                 {
    1089           0 :                     pStartMenu->bInCallback = true;
    1090           0 :                     pStartMenu->aDeactivateHdl.Call( this );
    1091           0 :                     pStartMenu->bInCallback = false;
    1092             :                 }
    1093             :             }
    1094             :         }
    1095             :     }
    1096             : 
    1097          24 :     if( !aDelData.isDeleted() )
    1098             :     {
    1099          24 :         bInCallback = false;
    1100          24 :     }
    1101          24 : }
    1102             : 
    1103          26 : void Menu::Highlight()
    1104             : {
    1105          26 :     ImplMenuDelData aDelData( this );
    1106             : 
    1107          26 :     Menu* pStartMenu = ImplGetStartMenu();
    1108          26 :     if ( !aHighlightHdl.Call( this ) && !aDelData.isDeleted() )
    1109             :     {
    1110          26 :         if ( pStartMenu && ( pStartMenu != this ) )
    1111           0 :             pStartMenu->aHighlightHdl.Call( this );
    1112          26 :     }
    1113          26 : }
    1114             : 
    1115           0 : void Menu::ImplSelect()
    1116             : {
    1117           0 :     MenuItemData* pData = GetItemList()->GetData( nSelectedId );
    1118           0 :     if ( pData && (pData->nBits & MIB_AUTOCHECK) )
    1119             :     {
    1120           0 :         bool bChecked = IsItemChecked( nSelectedId );
    1121           0 :         if ( pData->nBits & MIB_RADIOCHECK )
    1122             :         {
    1123           0 :             if ( !bChecked )
    1124           0 :                 CheckItem( nSelectedId, true );
    1125             :         }
    1126             :         else
    1127           0 :             CheckItem( nSelectedId, !bChecked );
    1128             :     }
    1129             : 
    1130             :     // call select
    1131           0 :     ImplSVData* pSVData = ImplGetSVData();
    1132           0 :     pSVData->maAppData.mpActivePopupMenu = NULL;        // if new execute in select()
    1133           0 :     Application::PostUserEvent( nEventId, LINK( this, Menu, ImplCallSelect ) );
    1134           0 : }
    1135             : 
    1136           0 : void Menu::Select()
    1137             : {
    1138           0 :     ImplMenuDelData aDelData( this );
    1139             : 
    1140           0 :     ImplCallEventListeners( VCLEVENT_MENU_SELECT, GetItemPos( GetCurItemId() ) );
    1141           0 :     if ( !aDelData.isDeleted() && !aSelectHdl.Call( this ) )
    1142             :     {
    1143           0 :         if( !aDelData.isDeleted() )
    1144             :         {
    1145           0 :             Menu* pStartMenu = ImplGetStartMenu();
    1146           0 :             if ( pStartMenu && ( pStartMenu != this ) )
    1147             :             {
    1148           0 :                 pStartMenu->nSelectedId = nSelectedId;
    1149           0 :                 pStartMenu->aSelectHdl.Call( this );
    1150             :             }
    1151             :         }
    1152           0 :     }
    1153           0 : }
    1154             : 
    1155             : #if defined(MACOSX)
    1156             : void Menu::ImplSelectWithStart( Menu* pSMenu )
    1157             : {
    1158             :     Menu* pOldStartedFrom = pStartedFrom;
    1159             :     pStartedFrom = pSMenu;
    1160             :     Menu* pOldStartedStarted = pOldStartedFrom ? pOldStartedFrom->pStartedFrom : NULL;
    1161             :     Select();
    1162             :     if( pOldStartedFrom )
    1163             :         pOldStartedFrom->pStartedFrom = pOldStartedStarted;
    1164             :     pStartedFrom = pOldStartedFrom;
    1165             : }
    1166             : #endif
    1167             : 
    1168           0 : void Menu::RequestHelp( const HelpEvent& )
    1169             : {
    1170           0 : }
    1171             : 
    1172      358575 : void Menu::ImplCallEventListeners( sal_uLong nEvent, sal_uInt16 nPos )
    1173             : {
    1174      358575 :     ImplMenuDelData aDelData( this );
    1175             : 
    1176      717150 :     VclMenuEvent aEvent( this, nEvent, nPos );
    1177             : 
    1178             :     // This is needed by atk accessibility bridge
    1179      358575 :     if ( nEvent == VCLEVENT_MENU_HIGHLIGHT )
    1180             :     {
    1181          26 :         ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
    1182             :     }
    1183             : 
    1184      358575 :     if ( !aDelData.isDeleted() )
    1185      358575 :         maEventListeners.Call( &aEvent );
    1186             : 
    1187      358575 :     if( !aDelData.isDeleted() )
    1188             :     {
    1189      358575 :         Menu* pMenu = this;
    1190     1075883 :         while ( pMenu )
    1191             :         {
    1192      358733 :             maChildEventListeners.Call( &aEvent );
    1193             : 
    1194      358733 :             if( aDelData.isDeleted() )
    1195           0 :                 break;
    1196             : 
    1197      358733 :             pMenu = ( pMenu->pStartedFrom != pMenu ) ? pMenu->pStartedFrom : NULL;
    1198             :         }
    1199      358575 :     }
    1200      358575 : }
    1201             : 
    1202        7012 : void Menu::AddEventListener( const Link& rEventListener )
    1203             : {
    1204        7012 :     maEventListeners.addListener( rEventListener );
    1205        7012 : }
    1206             : 
    1207        9044 : void Menu::RemoveEventListener( const Link& rEventListener )
    1208             : {
    1209        9044 :     maEventListeners.removeListener( rEventListener );
    1210        9044 : }
    1211             : 
    1212      219608 : void Menu::InsertItem(sal_uInt16 nItemId, const OUString& rStr, MenuItemBits nItemBits,
    1213             :     const OString &rIdent, sal_uInt16 nPos)
    1214             : {
    1215             :     DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
    1216             :     DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
    1217             :                 "Menu::InsertItem(): ItemId already exists" );
    1218             : 
    1219             :     // if Position > ItemCount, append
    1220      219608 :     if ( nPos >= pItemList->size() )
    1221      219607 :         nPos = MENU_APPEND;
    1222             : 
    1223             :     // put Item in MenuItemList
    1224             :     MenuItemData* pData = pItemList->Insert(nItemId, MENUITEM_STRING,
    1225      219608 :                              nItemBits, rStr, Image(), this, nPos, rIdent);
    1226             : 
    1227             :     // update native menu
    1228      219608 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
    1229           0 :         ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
    1230             : 
    1231      219608 :     Window* pWin = ImplGetWindow();
    1232      219608 :     delete mpLayoutData, mpLayoutData = NULL;
    1233      219608 :     if ( pWin )
    1234             :     {
    1235          57 :         ImplCalcSize( pWin );
    1236          57 :         if ( pWin->IsVisible() )
    1237          57 :             pWin->Invalidate();
    1238             :     }
    1239      219608 :     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
    1240      219608 : }
    1241             : 
    1242           0 : void Menu::InsertItem(sal_uInt16 nItemId, const Image& rImage,
    1243             :     MenuItemBits nItemBits, const OString &rIdent, sal_uInt16 nPos)
    1244             : {
    1245           0 :     InsertItem(nItemId, OUString(), nItemBits, rIdent, nPos);
    1246           0 :     SetItemImage( nItemId, rImage );
    1247           0 : }
    1248             : 
    1249       16166 : void Menu::InsertItem(sal_uInt16 nItemId, const OUString& rStr,
    1250             :     const Image& rImage, MenuItemBits nItemBits,
    1251             :     const OString &rIdent, sal_uInt16 nPos)
    1252             : {
    1253       16166 :     InsertItem(nItemId, rStr, nItemBits, rIdent, nPos);
    1254       16166 :     SetItemImage( nItemId, rImage );
    1255       16166 : }
    1256             : 
    1257        3862 : void Menu::InsertItem( const ResId& rResId, sal_uInt16 nPos )
    1258             : {
    1259        3862 :     ResMgr* pMgr = rResId.GetResMgr();
    1260        3862 :     if( ! pMgr )
    1261        3862 :         return;
    1262             : 
    1263             :     sal_uLong              nObjMask;
    1264             : 
    1265        3862 :     GetRes( rResId.SetRT( RSC_MENUITEM ) );
    1266        3862 :     nObjMask    = ReadLongRes();
    1267             : 
    1268        3862 :     bool bSep = false;
    1269        3862 :     if ( nObjMask & RSC_MENUITEM_SEPARATOR )
    1270          50 :         bSep = ReadShortRes() != 0;
    1271             : 
    1272        3862 :     sal_uInt16 nItemId = 1;
    1273        3862 :     if ( nObjMask & RSC_MENUITEM_ID )
    1274        2968 :         nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
    1275             : 
    1276        3862 :     MenuItemBits nStatus = 0;
    1277        3862 :     if ( nObjMask & RSC_MENUITEM_STATUS )
    1278        3391 :         nStatus = sal::static_int_cast<MenuItemBits>(ReadLongRes());
    1279             : 
    1280        3862 :     OUString aText;
    1281        3862 :     if ( nObjMask & RSC_MENUITEM_TEXT )
    1282        3812 :         aText = ReadStringRes();
    1283             : 
    1284             :     // create item
    1285        3862 :     if ( nObjMask & RSC_MENUITEM_BITMAP )
    1286             :     {
    1287           0 :         if ( !bSep )
    1288             :         {
    1289           0 :             Bitmap aBmp( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
    1290           0 :             Image const aImg(aBmp);
    1291           0 :             if ( !aText.isEmpty() )
    1292           0 :                 InsertItem( nItemId, aText, aImg, nStatus, OString(), nPos );
    1293             :             else
    1294           0 :                 InsertItem( nItemId, aImg, nStatus, OString(), nPos );
    1295             :         }
    1296           0 :         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
    1297             :     }
    1298        3862 :     else if ( !bSep )
    1299        3812 :         InsertItem(nItemId, aText, nStatus, OString(), nPos);
    1300        3862 :     if ( bSep )
    1301          50 :         InsertSeparator(OString(), nPos);
    1302             : 
    1303        7724 :     OUString aHelpText;
    1304        3862 :     if ( nObjMask & RSC_MENUITEM_HELPTEXT )
    1305             :     {
    1306           0 :         aHelpText = ReadStringRes();
    1307           0 :         if( !bSep )
    1308           0 :             SetHelpText( nItemId, aHelpText );
    1309             :     }
    1310             : 
    1311        3862 :     if ( nObjMask & RSC_MENUITEM_HELPID )
    1312             :     {
    1313         419 :         OString aHelpId( ReadByteStringRes() );
    1314         419 :         if ( !bSep )
    1315         419 :             SetHelpId( nItemId, aHelpId );
    1316             :     }
    1317             : 
    1318        3862 :     if( !bSep )
    1319        3812 :         SetHelpText( nItemId, aHelpText );
    1320             : 
    1321        3862 :     if ( nObjMask & RSC_MENUITEM_KEYCODE )
    1322             :     {
    1323           0 :         if ( !bSep )
    1324           0 :             SetAccelKey( nItemId, KeyCode( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) ) );
    1325           0 :         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
    1326             :     }
    1327        3862 :     if( nObjMask & RSC_MENUITEM_CHECKED )
    1328             :     {
    1329           0 :         if ( !bSep )
    1330           0 :             CheckItem( nItemId, ReadShortRes() != 0 );
    1331             :     }
    1332        3862 :     if ( nObjMask & RSC_MENUITEM_DISABLE )
    1333             :     {
    1334           0 :         if ( !bSep )
    1335           0 :             EnableItem( nItemId, ReadShortRes() == 0 );
    1336             :     }
    1337        3862 :     if ( nObjMask & RSC_MENUITEM_COMMAND )
    1338             :     {
    1339          15 :         OUString aCommandStr = ReadStringRes();
    1340          15 :         if ( !bSep )
    1341          15 :             SetItemCommand( nItemId, aCommandStr );
    1342             :     }
    1343        3862 :     if ( nObjMask & RSC_MENUITEM_MENU )
    1344             :     {
    1345           4 :         if ( !bSep )
    1346             :         {
    1347           4 :             MenuItemData* pData = GetItemList()->GetData( nItemId );
    1348           4 :             if ( pData )
    1349             :             {
    1350           4 :                 PopupMenu* pSubMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
    1351           4 :                 pData->pAutoSubMenu = pSubMenu;
    1352             :                 // #111060# keep track of this pointer, may be it will be deleted from outside
    1353           4 :                 pSubMenu->pRefAutoSubMenu = &pData->pAutoSubMenu;
    1354           4 :                 SetPopupMenu( nItemId, pSubMenu );
    1355             :             }
    1356             :         }
    1357           4 :         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
    1358             :     }
    1359        7724 :     delete mpLayoutData, mpLayoutData = NULL;
    1360             : }
    1361             : 
    1362       38295 : void Menu::InsertSeparator(const OString &rIdent, sal_uInt16 nPos)
    1363             : {
    1364             :     // do nothing if it's a menu bar
    1365       38295 :     if ( bIsMenuBar )
    1366       38295 :         return;
    1367             : 
    1368             :     // if position > ItemCount, append
    1369       38295 :     if ( nPos >= pItemList->size() )
    1370       38295 :         nPos = MENU_APPEND;
    1371             : 
    1372             :     // put separator in item list
    1373       38295 :     pItemList->InsertSeparator(rIdent, nPos);
    1374             : 
    1375             :     // update native menu
    1376       38295 :     size_t itemPos = ( nPos != MENU_APPEND ) ? nPos : pItemList->size() - 1;
    1377       38295 :     MenuItemData *pData = pItemList->GetDataFromPos( itemPos );
    1378       38295 :     if( ImplGetSalMenu() && pData && pData->pSalMenuItem )
    1379           0 :         ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
    1380             : 
    1381       38295 :     delete mpLayoutData, mpLayoutData = NULL;
    1382             : 
    1383       38295 :     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
    1384             : }
    1385             : 
    1386          61 : void Menu::RemoveItem( sal_uInt16 nPos )
    1387             : {
    1388          61 :     bool bRemove = false;
    1389             : 
    1390          61 :     if ( nPos < GetItemCount() )
    1391             :     {
    1392             :         // update native menu
    1393          61 :         if( ImplGetSalMenu() )
    1394           0 :             ImplGetSalMenu()->RemoveItem( nPos );
    1395             : 
    1396          61 :         pItemList->Remove( nPos );
    1397          61 :         bRemove = true;
    1398             :     }
    1399             : 
    1400          61 :     Window* pWin = ImplGetWindow();
    1401          61 :     if ( pWin )
    1402             :     {
    1403          57 :         ImplCalcSize( pWin );
    1404          57 :         if ( pWin->IsVisible() )
    1405          57 :             pWin->Invalidate();
    1406             :     }
    1407          61 :     delete mpLayoutData, mpLayoutData = NULL;
    1408             : 
    1409          61 :     if ( bRemove )
    1410          61 :         ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM, nPos );
    1411          61 : }
    1412             : 
    1413       10125 : void ImplCopyItem( Menu* pThis, const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos,
    1414             :                   sal_uInt16 nMode = 0 )
    1415             : {
    1416       10125 :     MenuItemType eType = rMenu.GetItemType( nPos );
    1417             : 
    1418       10125 :     if ( eType == MENUITEM_DONTKNOW )
    1419           0 :         return;
    1420             : 
    1421       10125 :     if ( eType == MENUITEM_SEPARATOR )
    1422        2025 :         pThis->InsertSeparator( OString(), nNewPos );
    1423             :     else
    1424             :     {
    1425        8100 :         sal_uInt16 nId = rMenu.GetItemId( nPos );
    1426             : 
    1427             :         DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
    1428             :                     "Menu::CopyItem(): ItemId already exists" );
    1429             : 
    1430        8100 :         MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
    1431             : 
    1432        8100 :         if (!pData)
    1433           0 :             return;
    1434             : 
    1435        8100 :         if ( eType == MENUITEM_STRINGIMAGE )
    1436        8083 :             pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, pData->sIdent, nNewPos );
    1437          17 :         else if ( eType == MENUITEM_STRING )
    1438          17 :             pThis->InsertItem( nId, pData->aText, pData->nBits, pData->sIdent, nNewPos );
    1439             :         else
    1440           0 :             pThis->InsertItem( nId, pData->aImage, pData->nBits, pData->sIdent, nNewPos );
    1441             : 
    1442        8100 :         if ( rMenu.IsItemChecked( nId ) )
    1443           0 :             pThis->CheckItem( nId, true );
    1444        8100 :         if ( !rMenu.IsItemEnabled( nId ) )
    1445           0 :             pThis->EnableItem( nId, false );
    1446        8100 :         pThis->SetHelpId( nId, pData->aHelpId );
    1447        8100 :         pThis->SetHelpText( nId, pData->aHelpText );
    1448        8100 :         pThis->SetAccelKey( nId, pData->aAccelKey );
    1449        8100 :         pThis->SetItemCommand( nId, pData->aCommandStr );
    1450        8100 :         pThis->SetHelpCommand( nId, pData->aHelpCommandStr );
    1451             : 
    1452        8100 :         PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
    1453        8100 :         if ( pSubMenu )
    1454             :         {
    1455             :             // create auto-copy
    1456           0 :             if ( nMode == 1 )
    1457             :             {
    1458           0 :                 PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
    1459           0 :                 pThis->SetPopupMenu( nId, pNewMenu );
    1460             :             }
    1461             :             else
    1462           0 :                 pThis->SetPopupMenu( nId, pSubMenu );
    1463             :         }
    1464             :     }
    1465             : }
    1466             : 
    1467           0 : void Menu::CopyItem( const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos )
    1468             : {
    1469           0 :     ImplCopyItem( this, rMenu, nPos, nNewPos );
    1470           0 : }
    1471             : 
    1472         682 : void Menu::Clear()
    1473             : {
    1474         739 :     for ( sal_uInt16 i = GetItemCount(); i; i-- )
    1475          57 :         RemoveItem( 0 );
    1476         682 : }
    1477             : 
    1478      111551 : sal_uInt16 Menu::GetItemCount() const
    1479             : {
    1480      111551 :     return (sal_uInt16)pItemList->size();
    1481             : }
    1482             : 
    1483           8 : sal_uInt16 Menu::ImplGetVisibleItemCount() const
    1484             : {
    1485           8 :     sal_uInt16 nItems = 0;
    1486         224 :     for ( size_t n = pItemList->size(); n; )
    1487             :     {
    1488         208 :         if ( ImplIsVisible( --n ) )
    1489         208 :             nItems++;
    1490             :     }
    1491           8 :     return nItems;
    1492             : }
    1493             : 
    1494           0 : sal_uInt16 Menu::ImplGetFirstVisible() const
    1495             : {
    1496           0 :     for ( size_t n = 0; n < pItemList->size(); n++ )
    1497             :     {
    1498           0 :         if ( ImplIsVisible( n ) )
    1499           0 :             return n;
    1500             :     }
    1501           0 :     return ITEMPOS_INVALID;
    1502             : }
    1503             : 
    1504           0 : sal_uInt16 Menu::ImplGetPrevVisible( sal_uInt16 nPos ) const
    1505             : {
    1506           0 :     for ( size_t n = nPos; n; )
    1507             :     {
    1508           0 :         if ( n && ImplIsVisible( --n ) )
    1509           0 :             return n;
    1510             :     }
    1511           0 :     return ITEMPOS_INVALID;
    1512             : }
    1513             : 
    1514           0 : sal_uInt16 Menu::ImplGetNextVisible( sal_uInt16 nPos ) const
    1515             : {
    1516           0 :     for ( size_t n = nPos+1; n < pItemList->size(); n++ )
    1517             :     {
    1518           0 :         if ( ImplIsVisible( n ) )
    1519           0 :             return n;
    1520             :     }
    1521           0 :     return ITEMPOS_INVALID;
    1522             : }
    1523             : 
    1524      305750 : sal_uInt16 Menu::GetItemId(sal_uInt16 nPos) const
    1525             : {
    1526      305750 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    1527             : 
    1528      305750 :     if ( pData )
    1529      305750 :         return pData->nId;
    1530             :     else
    1531           0 :         return 0;
    1532             : }
    1533             : 
    1534           0 : sal_uInt16 Menu::GetItemId(const OString &rIdent) const
    1535             : {
    1536           0 :     for (size_t n = 0; n < pItemList->size(); ++n)
    1537             :     {
    1538           0 :         MenuItemData* pData = pItemList->GetDataFromPos(n);
    1539           0 :         if (pData && pData->sIdent == rIdent)
    1540           0 :             return pData->nId;
    1541             :     }
    1542           0 :     return MENU_ITEM_NOTFOUND;
    1543             : }
    1544             : 
    1545        1678 : sal_uInt16 Menu::GetItemPos( sal_uInt16 nItemId ) const
    1546             : {
    1547             :     size_t          nPos;
    1548        1678 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1549             : 
    1550        1678 :     if ( pData )
    1551        1662 :         return (sal_uInt16)nPos;
    1552             :     else
    1553          16 :         return MENU_ITEM_NOTFOUND;
    1554             : }
    1555             : 
    1556      239601 : MenuItemType Menu::GetItemType( sal_uInt16 nPos ) const
    1557             : {
    1558      239601 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    1559             : 
    1560      239601 :     if ( pData )
    1561      231501 :         return pData->eType;
    1562             :     else
    1563        8100 :         return MENUITEM_DONTKNOW;
    1564             : }
    1565             : 
    1566          34 : void Menu::SetHighlightItem( sal_uInt16 nItem )
    1567             : {
    1568          34 :     nHighlightedItem = nItem;
    1569          34 : }
    1570             : 
    1571          26 : sal_uInt16 Menu::GetCurItemId() const
    1572             : {
    1573          26 :     return nSelectedId;
    1574             : }
    1575             : 
    1576           0 : OString Menu::GetCurItemIdent() const
    1577             : {
    1578           0 :     const MenuItemData* pData = pItemList->GetData(nSelectedId);
    1579           0 :     return pData ? pData->sIdent : OString();
    1580             : }
    1581             : 
    1582           0 : OString Menu::GetItemIdent(sal_uInt16 nId) const
    1583             : {
    1584           0 :     const MenuItemData* pData = pItemList->GetData(nId);
    1585           0 :     return pData ? pData->sIdent : OString();
    1586             : }
    1587             : 
    1588        7843 : void Menu::SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits )
    1589             : {
    1590        7843 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1591        7843 :     if ( pData )
    1592        7843 :         pData->nBits = nBits;
    1593        7843 : }
    1594             : 
    1595        9517 : MenuItemBits Menu::GetItemBits( sal_uInt16 nItemId ) const
    1596             : {
    1597        9517 :     MenuItemBits nBits = 0;
    1598        9517 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1599        9517 :     if ( pData )
    1600        9517 :         nBits = pData->nBits;
    1601        9517 :     return nBits;
    1602             : }
    1603             : 
    1604        8140 : void Menu::SetUserValue( sal_uInt16 nItemId, sal_uLong nValue )
    1605             : {
    1606        8140 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1607        8140 :     if ( pData )
    1608        8140 :         pData->nUserValue = nValue;
    1609        8140 : }
    1610             : 
    1611       41109 : sal_uLong Menu::GetUserValue( sal_uInt16 nItemId ) const
    1612             : {
    1613       41109 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1614       41109 :     return pData ? pData->nUserValue : 0;
    1615             : }
    1616             : 
    1617       37606 : void Menu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu )
    1618             : {
    1619             :     size_t          nPos;
    1620       37606 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1621             : 
    1622             :     // Item does not exist -> return NULL
    1623       37606 :     if ( !pData )
    1624           0 :         return;
    1625             : 
    1626             :     // same menu, nothing to do
    1627       37606 :     if ( (PopupMenu*)pData->pSubMenu == pMenu )
    1628           0 :         return;
    1629             : 
    1630             :     // data exchange
    1631       37606 :     pData->pSubMenu = pMenu;
    1632             : 
    1633             :     // #112023# Make sure pStartedFrom does not point to invalid (old) data
    1634       37606 :     if ( pData->pSubMenu )
    1635       31559 :         pData->pSubMenu->pStartedFrom = 0;
    1636             : 
    1637             :     // set native submenu
    1638       37606 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
    1639             :     {
    1640           0 :         if( pMenu )
    1641           0 :             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, pMenu->ImplGetSalMenu(), nPos );
    1642             :         else
    1643           0 :             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, NULL, nPos );
    1644             :     }
    1645             : 
    1646       37606 :     ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED, nPos );
    1647             : }
    1648             : 
    1649      269206 : PopupMenu* Menu::GetPopupMenu( sal_uInt16 nItemId ) const
    1650             : {
    1651      269206 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1652             : 
    1653      269206 :     if ( pData )
    1654      261069 :         return (PopupMenu*)(pData->pSubMenu);
    1655             :     else
    1656        8137 :         return NULL;
    1657             : }
    1658             : 
    1659        8255 : void Menu::SetAccelKey( sal_uInt16 nItemId, const KeyCode& rKeyCode )
    1660             : {
    1661             :     size_t          nPos;
    1662        8255 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1663             : 
    1664        8255 :     if ( !pData )
    1665        8255 :         return;
    1666             : 
    1667        8255 :     if ( pData->aAccelKey == rKeyCode )
    1668        8255 :         return;
    1669             : 
    1670           0 :     pData->aAccelKey = rKeyCode;
    1671             : 
    1672             :     // update native menu
    1673           0 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
    1674           0 :         ImplGetSalMenu()->SetAccelerator( nPos, pData->pSalMenuItem, rKeyCode, rKeyCode.GetName() );
    1675             : }
    1676             : 
    1677           1 : KeyCode Menu::GetAccelKey( sal_uInt16 nItemId ) const
    1678             : {
    1679           1 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1680             : 
    1681           1 :     if ( pData )
    1682           1 :         return pData->aAccelKey;
    1683             :     else
    1684           0 :         return KeyCode();
    1685             : }
    1686             : 
    1687           1 : KeyEvent Menu::GetActivationKey( sal_uInt16 nItemId ) const
    1688             : {
    1689           1 :     KeyEvent aRet;
    1690           1 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1691           1 :     if( pData )
    1692             :     {
    1693           1 :         sal_Int32 nPos = pData->aText.indexOf( '~' );
    1694           1 :         if( nPos != -1 && nPos < pData->aText.getLength()-1 )
    1695             :         {
    1696           1 :             sal_uInt16 nCode = 0;
    1697           1 :             sal_Unicode cAccel = pData->aText[nPos+1];
    1698           1 :             if( cAccel >= 'a' && cAccel <= 'z' )
    1699           0 :                 nCode = KEY_A + (cAccel-'a');
    1700           1 :             else if( cAccel >= 'A' && cAccel <= 'Z' )
    1701           1 :                 nCode = KEY_A + (cAccel-'A');
    1702           0 :             else if( cAccel >= '0' && cAccel <= '9' )
    1703           0 :                 nCode = KEY_0 + (cAccel-'0');
    1704           1 :             if(nCode )
    1705           1 :                 aRet = KeyEvent( cAccel, KeyCode( nCode, KEY_MOD2 ) );
    1706             :         }
    1707             : 
    1708             :     }
    1709           1 :     return aRet;
    1710             : }
    1711             : 
    1712         899 : void Menu::CheckItem( sal_uInt16 nItemId, bool bCheck )
    1713             : {
    1714             :     size_t          nPos;
    1715         899 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1716             : 
    1717         899 :     if ( !pData || pData->bChecked == bCheck )
    1718         942 :         return;
    1719             : 
    1720             :     // if radio-check, then uncheck previous
    1721         858 :     if ( bCheck && (pData->nBits & MIB_AUTOCHECK) &&
    1722           2 :          (pData->nBits & MIB_RADIOCHECK) )
    1723             :     {
    1724             :         MenuItemData*   pGroupData;
    1725             :         sal_uInt16          nGroupPos;
    1726           2 :         sal_uInt16          nItemCount = GetItemCount();
    1727           2 :         bool            bFound = false;
    1728             : 
    1729           2 :         nGroupPos = nPos;
    1730           4 :         while ( nGroupPos )
    1731             :         {
    1732           0 :             pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
    1733           0 :             if ( pGroupData->nBits & MIB_RADIOCHECK )
    1734             :             {
    1735           0 :                 if ( IsItemChecked( pGroupData->nId ) )
    1736             :                 {
    1737           0 :                     CheckItem( pGroupData->nId, false );
    1738           0 :                     bFound = true;
    1739           0 :                     break;
    1740             :                 }
    1741             :             }
    1742             :             else
    1743           0 :                 break;
    1744           0 :             nGroupPos--;
    1745             :         }
    1746             : 
    1747           2 :         if ( !bFound )
    1748             :         {
    1749           2 :             nGroupPos = nPos+1;
    1750           8 :             while ( nGroupPos < nItemCount )
    1751             :             {
    1752           4 :                 pGroupData = pItemList->GetDataFromPos( nGroupPos );
    1753           4 :                 if ( pGroupData->nBits & MIB_RADIOCHECK )
    1754             :                 {
    1755           4 :                     if ( IsItemChecked( pGroupData->nId ) )
    1756             :                     {
    1757           0 :                         CheckItem( pGroupData->nId, false );
    1758           0 :                         break;
    1759             :                     }
    1760             :                 }
    1761             :                 else
    1762           0 :                     break;
    1763           4 :                 nGroupPos++;
    1764             :             }
    1765             :         }
    1766             :     }
    1767             : 
    1768         856 :     pData->bChecked = bCheck;
    1769             : 
    1770             :     // update native menu
    1771         856 :     if( ImplGetSalMenu() )
    1772           0 :         ImplGetSalMenu()->CheckItem( nPos, bCheck );
    1773             : 
    1774         856 :     ImplCallEventListeners( bCheck ? VCLEVENT_MENU_ITEMCHECKED : VCLEVENT_MENU_ITEMUNCHECKED, nPos );
    1775             : }
    1776             : 
    1777       11715 : bool Menu::IsItemChecked( sal_uInt16 nItemId ) const
    1778             : {
    1779             :     size_t          nPos;
    1780       11715 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1781             : 
    1782       11715 :     if ( !pData )
    1783           0 :         return false;
    1784             : 
    1785       11715 :     return pData->bChecked;
    1786             : }
    1787             : 
    1788        6197 : void Menu::EnableItem( sal_uInt16 nItemId, bool bEnable )
    1789             : {
    1790             :     size_t          nPos;
    1791        6197 :     MenuItemData*   pItemData = pItemList->GetData( nItemId, nPos );
    1792             : 
    1793        6197 :     if ( pItemData && ( pItemData->bEnabled != bEnable ) )
    1794             :     {
    1795        6082 :         pItemData->bEnabled = bEnable;
    1796             : 
    1797        6082 :         Window* pWin = ImplGetWindow();
    1798        6082 :         if ( pWin && pWin->IsVisible() )
    1799             :         {
    1800             :             DBG_ASSERT( bIsMenuBar, "Menu::EnableItem - Popup visible!" );
    1801           0 :             long nX = 0;
    1802           0 :             size_t nCount = pItemList->size();
    1803           0 :             for ( size_t n = 0; n < nCount; n++ )
    1804             :             {
    1805           0 :                 MenuItemData* pData = pItemList->GetDataFromPos( n );
    1806           0 :                 if ( n == nPos )
    1807             :                 {
    1808           0 :                     pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
    1809           0 :                     break;
    1810             :                 }
    1811           0 :                 nX += pData->aSz.Width();
    1812             :             }
    1813             :         }
    1814             :         // update native menu
    1815        6082 :         if( ImplGetSalMenu() )
    1816           0 :             ImplGetSalMenu()->EnableItem( nPos, bEnable );
    1817             : 
    1818        6082 :         ImplCallEventListeners( bEnable ? VCLEVENT_MENU_ENABLE : VCLEVENT_MENU_DISABLE, nPos );
    1819             :     }
    1820        6197 : }
    1821             : 
    1822       12456 : bool Menu::IsItemEnabled( sal_uInt16 nItemId ) const
    1823             : {
    1824             :     size_t          nPos;
    1825       12456 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1826             : 
    1827       12456 :     if ( !pData )
    1828           0 :         return false;
    1829             : 
    1830       12456 :     return pData->bEnabled;
    1831             : }
    1832             : 
    1833         150 : void Menu::ShowItem( sal_uInt16 nItemId, bool bVisible )
    1834             : {
    1835             :     size_t          nPos;
    1836         150 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1837             : 
    1838             :     DBG_ASSERT( !bIsMenuBar, "Menu::ShowItem - ignored for menu bar entries!" );
    1839         150 :     if ( !bIsMenuBar && pData && ( pData->bVisible != bVisible ) )
    1840             :     {
    1841           0 :         Window* pWin = ImplGetWindow();
    1842           0 :         if ( pWin && pWin->IsVisible() )
    1843             :         {
    1844             :             DBG_ASSERT( false, "Menu::ShowItem - ignored for visible popups!" );
    1845           0 :             return;
    1846             :         }
    1847           0 :         pData->bVisible = bVisible;
    1848             : 
    1849             :         // update native menu
    1850           0 :         if( ImplGetSalMenu() )
    1851           0 :             ImplGetSalMenu()->ShowItem( nPos, bVisible );
    1852             :     }
    1853             : }
    1854             : 
    1855        6069 : void Menu::SetItemText( sal_uInt16 nItemId, const OUString& rStr )
    1856             : {
    1857             :     size_t          nPos;
    1858        6069 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1859             : 
    1860        6069 :     if ( !pData )
    1861        6069 :         return;
    1862             : 
    1863        6069 :     if ( !rStr.equals( pData->aText ) )
    1864             :     {
    1865        6069 :         pData->aText = rStr;
    1866        6069 :         ImplSetMenuItemData( pData );
    1867             :         // update native menu
    1868        6069 :         if( ImplGetSalMenu() && pData->pSalMenuItem )
    1869           0 :             ImplGetSalMenu()->SetItemText( nPos, pData->pSalMenuItem, rStr );
    1870             : 
    1871        6069 :         Window* pWin = ImplGetWindow();
    1872        6069 :         delete mpLayoutData, mpLayoutData = NULL;
    1873        6069 :         if ( pWin && IsMenuBar() )
    1874             :         {
    1875          54 :             ImplCalcSize( pWin );
    1876          54 :             if ( pWin->IsVisible() )
    1877          54 :                 pWin->Invalidate();
    1878             :         }
    1879             : 
    1880        6069 :         ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED, nPos );
    1881             :     }
    1882             : }
    1883             : 
    1884       11049 : OUString Menu::GetItemText( sal_uInt16 nItemId ) const
    1885             : {
    1886             :     size_t          nPos;
    1887       11049 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1888             : 
    1889       11049 :     if ( pData )
    1890       11049 :         return pData->aText;
    1891             : 
    1892           0 :     return OUString();
    1893             : }
    1894             : 
    1895       24318 : void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
    1896             : {
    1897             :     size_t          nPos;
    1898       24318 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1899             : 
    1900       24318 :     if ( !pData )
    1901       24318 :         return;
    1902             : 
    1903       24318 :     pData->aImage = rImage;
    1904       24318 :     ImplSetMenuItemData( pData );
    1905             : 
    1906             :     // update native menu
    1907       24318 :     if( ImplGetSalMenu() && pData->pSalMenuItem )
    1908           0 :         ImplGetSalMenu()->SetItemImage( nPos, pData->pSalMenuItem, rImage );
    1909             : }
    1910             : 
    1911           0 : static inline Image ImplRotImage( const Image& rImage, long nAngle10 )
    1912             : {
    1913           0 :     Image       aRet;
    1914           0 :     BitmapEx    aBmpEx( rImage.GetBitmapEx() );
    1915             : 
    1916           0 :     aBmpEx.Rotate( nAngle10, COL_WHITE );
    1917             : 
    1918           0 :     return Image( aBmpEx );
    1919             : }
    1920             : 
    1921           0 : void Menu::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
    1922             : {
    1923             :     size_t          nPos;
    1924           0 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1925             : 
    1926           0 :     if ( pData )
    1927             :     {
    1928           0 :         long nDeltaAngle = (nAngle10 - pData->nItemImageAngle) % 3600;
    1929           0 :         while( nDeltaAngle < 0 )
    1930           0 :             nDeltaAngle += 3600;
    1931             : 
    1932           0 :         pData->nItemImageAngle = nAngle10;
    1933           0 :         if( nDeltaAngle && !!pData->aImage )
    1934           0 :             pData->aImage = ImplRotImage( pData->aImage, nDeltaAngle );
    1935             :     }
    1936           0 : }
    1937             : 
    1938           0 : static inline Image ImplMirrorImage( const Image& rImage )
    1939             : {
    1940           0 :     Image       aRet;
    1941           0 :     BitmapEx    aBmpEx( rImage.GetBitmapEx() );
    1942             : 
    1943           0 :     aBmpEx.Mirror( BMP_MIRROR_HORZ );
    1944             : 
    1945           0 :     return Image( aBmpEx );
    1946             : }
    1947             : 
    1948           0 : void Menu::SetItemImageMirrorMode( sal_uInt16 nItemId, bool bMirror )
    1949             : {
    1950             :     size_t          nPos;
    1951           0 :     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
    1952             : 
    1953           0 :     if ( pData )
    1954             :     {
    1955           0 :         if( ( pData->bMirrorMode && ! bMirror ) ||
    1956           0 :             ( ! pData->bMirrorMode && bMirror )
    1957             :             )
    1958             :         {
    1959           0 :             pData->bMirrorMode = bMirror ? true : false;
    1960           0 :             if( !!pData->aImage )
    1961           0 :                 pData->aImage = ImplMirrorImage( pData->aImage );
    1962             :         }
    1963             :     }
    1964           0 : }
    1965             : 
    1966         977 : Image Menu::GetItemImage( sal_uInt16 nItemId ) const
    1967             : {
    1968         977 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1969             : 
    1970         977 :     if ( pData )
    1971         977 :         return pData->aImage;
    1972             :     else
    1973           0 :         return Image();
    1974             : }
    1975             : 
    1976      229605 : void Menu::SetItemCommand( sal_uInt16 nItemId, const OUString& rCommand )
    1977             : {
    1978             :     size_t        nPos;
    1979      229605 :     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
    1980             : 
    1981      229605 :     if ( pData )
    1982      229605 :         pData->aCommandStr = rCommand;
    1983      229605 : }
    1984             : 
    1985      257595 : OUString Menu::GetItemCommand( sal_uInt16 nItemId ) const
    1986             : {
    1987      257595 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1988             : 
    1989      257595 :     if (pData)
    1990      257595 :         return pData->aCommandStr;
    1991             : 
    1992           0 :     return OUString();
    1993             : }
    1994             : 
    1995       59116 : void Menu::SetHelpCommand( sal_uInt16 nItemId, const OUString& rStr )
    1996             : {
    1997       59116 :     MenuItemData* pData = pItemList->GetData( nItemId );
    1998             : 
    1999       59116 :     if ( pData )
    2000       59116 :         pData->aHelpCommandStr = rStr;
    2001       59116 : }
    2002             : 
    2003       51016 : OUString Menu::GetHelpCommand( sal_uInt16 nItemId ) const
    2004             : {
    2005       51016 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2006             : 
    2007       51016 :     if ( pData )
    2008       51016 :         return pData->aHelpCommandStr;
    2009             : 
    2010           0 :     return OUString();
    2011             : }
    2012             : 
    2013       11912 : void Menu::SetHelpText( sal_uInt16 nItemId, const OUString& rStr )
    2014             : {
    2015       11912 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2016             : 
    2017       11912 :     if ( pData )
    2018       11912 :         pData->aHelpText = rStr;
    2019       11912 : }
    2020             : 
    2021         206 : OUString Menu::ImplGetHelpText( sal_uInt16 nItemId ) const
    2022             : {
    2023         206 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2024             : 
    2025         618 :     if ( pData && pData->aHelpText.isEmpty() &&
    2026         412 :          (( !pData->aHelpId.isEmpty()  ) || ( !pData->aCommandStr.isEmpty() )))
    2027             :     {
    2028         206 :         Help* pHelp = Application::GetHelp();
    2029         206 :         if ( pHelp )
    2030             :         {
    2031         206 :             if (!pData->aCommandStr.isEmpty())
    2032         206 :                 pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, NULL );
    2033         206 :             if (pData->aHelpText.isEmpty() && !pData->aHelpId.isEmpty())
    2034           0 :                 pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
    2035             :         }
    2036             :     }
    2037             : 
    2038         206 :     return OUString();
    2039             : }
    2040             : 
    2041         206 : OUString Menu::GetHelpText( sal_uInt16 nItemId ) const
    2042             : {
    2043         206 :     return ImplGetHelpText( nItemId );
    2044             : }
    2045             : 
    2046           0 : void Menu::SetTipHelpText( sal_uInt16 nItemId, const OUString& rStr )
    2047             : {
    2048           0 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2049             : 
    2050           0 :     if ( pData )
    2051           0 :         pData->aTipHelpText = rStr;
    2052           0 : }
    2053             : 
    2054           2 : OUString Menu::GetTipHelpText( sal_uInt16 nItemId ) const
    2055             : {
    2056           2 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2057             : 
    2058           2 :     if ( pData )
    2059           2 :         return pData->aTipHelpText;
    2060             : 
    2061           0 :     return OUString();
    2062             : }
    2063             : 
    2064        8520 : void Menu::SetHelpId( sal_uInt16 nItemId, const OString& rHelpId )
    2065             : {
    2066        8520 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2067             : 
    2068        8520 :     if ( pData )
    2069        8520 :         pData->aHelpId = rHelpId;
    2070        8520 : }
    2071             : 
    2072           0 : OString Menu::GetHelpId( sal_uInt16 nItemId ) const
    2073             : {
    2074           0 :     OString aRet;
    2075             : 
    2076           0 :     MenuItemData* pData = pItemList->GetData( nItemId );
    2077             : 
    2078           0 :     if ( pData )
    2079             :     {
    2080           0 :         if ( !pData->aHelpId.isEmpty() )
    2081           0 :             aRet = pData->aHelpId;
    2082             :         else
    2083           0 :             aRet = OUStringToOString( pData->aCommandStr, RTL_TEXTENCODING_UTF8 );
    2084             :     }
    2085             : 
    2086           0 :     return aRet;
    2087             : }
    2088             : 
    2089         675 : Menu& Menu::operator=( const Menu& rMenu )
    2090             : {
    2091             :     // clean up
    2092         675 :     Clear();
    2093             : 
    2094             :     // copy items
    2095         675 :     sal_uInt16 nCount = rMenu.GetItemCount();
    2096       10800 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
    2097       10125 :         ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
    2098             : 
    2099         675 :     nDefaultItem = rMenu.nDefaultItem;
    2100         675 :     aActivateHdl = rMenu.aActivateHdl;
    2101         675 :     aDeactivateHdl = rMenu.aDeactivateHdl;
    2102         675 :     aHighlightHdl = rMenu.aHighlightHdl;
    2103         675 :     aSelectHdl = rMenu.aSelectHdl;
    2104         675 :     aTitleText = rMenu.aTitleText;
    2105         675 :     bIsMenuBar = rMenu.bIsMenuBar;
    2106             : 
    2107         675 :     return *this;
    2108             : }
    2109             : 
    2110       23514 : bool Menu::ImplIsVisible( sal_uInt16 nPos ) const
    2111             : {
    2112       23514 :     bool bVisible = true;
    2113             : 
    2114       23514 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    2115             :     // check general visibility first
    2116       23514 :     if( pData && !pData->bVisible )
    2117           0 :         bVisible = false;
    2118             : 
    2119       23514 :     if ( bVisible && pData && pData->eType == MENUITEM_SEPARATOR )
    2120             :     {
    2121         119 :         if( nPos == 0 ) // no separator should be shown at the very beginning
    2122           0 :             bVisible = false;
    2123             :         else
    2124             :         {
    2125             :             // always avoid adjacent separators
    2126         119 :             size_t nCount = pItemList->size();
    2127             :             size_t n;
    2128         119 :             MenuItemData* pNextData = NULL;
    2129             :             // search next visible item
    2130         119 :             for( n = nPos + 1; n < nCount; n++ )
    2131             :             {
    2132         119 :                 pNextData = pItemList->GetDataFromPos( n );
    2133         119 :                 if( pNextData && pNextData->bVisible )
    2134             :                 {
    2135         119 :                     if( pNextData->eType == MENUITEM_SEPARATOR || ImplIsVisible(n) )
    2136         119 :                         break;
    2137             :                 }
    2138             :             }
    2139         119 :             if( n == nCount ) // no next visible item
    2140           0 :                 bVisible = false;
    2141             :             // check for separator
    2142         119 :             if( pNextData && pNextData->bVisible && pNextData->eType == MENUITEM_SEPARATOR )
    2143           0 :                 bVisible = false;
    2144             : 
    2145         119 :             if( bVisible )
    2146             :             {
    2147         119 :                 for( n = nPos; n > 0; n-- )
    2148             :                 {
    2149         119 :                     pNextData = pItemList->GetDataFromPos( n-1 );
    2150         119 :                     if( pNextData && pNextData->bVisible )
    2151             :                     {
    2152         119 :                         if( pNextData->eType != MENUITEM_SEPARATOR && ImplIsVisible(n-1) )
    2153         119 :                             break;
    2154             :                     }
    2155             :                 }
    2156         119 :                 if( n == 0 ) // no previous visible item
    2157           0 :                     bVisible = false;
    2158             :             }
    2159             :         }
    2160             :     }
    2161             : 
    2162             :     // not allowed for menubar, as I do not know
    2163             :     // whether a menu-entry will disappear or will appear
    2164       23514 :     if ( bVisible && !bIsMenuBar && ( nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES ) &&
    2165           0 :         !( nMenuFlags & MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ) )
    2166             :     {
    2167           0 :         if( !pData ) // e.g. nPos == ITEMPOS_INVALID
    2168           0 :             bVisible = false;
    2169           0 :         else if ( pData->eType != MENUITEM_SEPARATOR ) // separators handled above
    2170             :         {
    2171             :             // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( true ) );
    2172           0 :             bVisible = pData->bEnabled; // do not check submenus as they might be filled at Activate().
    2173             :         }
    2174             :     }
    2175             : 
    2176       23514 :     return bVisible;
    2177             : }
    2178             : 
    2179        4374 : bool Menu::IsItemPosVisible( sal_uInt16 nItemPos ) const
    2180             : {
    2181        4374 :     return IsMenuVisible() && ImplIsVisible( nItemPos );
    2182             : }
    2183             : 
    2184        4410 : bool Menu::IsMenuVisible() const
    2185             : {
    2186        4410 :     return pWindow && pWindow->IsReallyVisible();
    2187             : }
    2188             : 
    2189           0 : bool Menu::ImplIsSelectable( sal_uInt16 nPos ) const
    2190             : {
    2191           0 :     bool bSelectable = true;
    2192             : 
    2193           0 :     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
    2194             :     // check general visibility first
    2195           0 :     if ( pData && ( pData->nBits & MIB_NOSELECT ) )
    2196           0 :         bSelectable = false;
    2197             : 
    2198           0 :     return bSelectable;
    2199             : }
    2200             : 
    2201           8 : void Menu::SelectItem( sal_uInt16 nItemId )
    2202             : {
    2203           8 :     if( bIsMenuBar )
    2204           8 :         static_cast<MenuBar*>(this)->SelectEntry( nItemId );
    2205             :     else
    2206           0 :         static_cast<PopupMenu*>(this)->SelectEntry( nItemId );
    2207           8 : }
    2208             : 
    2209        3241 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Menu::GetAccessible()
    2210             : {
    2211             :     // Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
    2212             :     // overwritten and may contain a disposed object when the initial menubar gets set again. So use the
    2213             :     // mxAccessible member only for sub menus.
    2214        3241 :     if ( pStartedFrom )
    2215             :     {
    2216        2276 :         for ( sal_uInt16 i = 0, nCount = pStartedFrom->GetItemCount(); i < nCount; ++i )
    2217             :         {
    2218        2276 :             sal_uInt16 nItemId = pStartedFrom->GetItemId( i );
    2219        2276 :             if ( static_cast< Menu* >( pStartedFrom->GetPopupMenu( nItemId ) ) == this )
    2220             :             {
    2221         760 :                 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xParent = pStartedFrom->GetAccessible();
    2222         760 :                 if ( xParent.is() )
    2223             :                 {
    2224         760 :                     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
    2225         760 :                     if ( xParentContext.is() )
    2226         760 :                         return xParentContext->getAccessibleChild( i );
    2227           0 :                 }
    2228             :             }
    2229             :         }
    2230             :     }
    2231        2481 :     else if ( !mxAccessible.is() )
    2232             :     {
    2233          25 :         UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
    2234          25 :         if ( pWrapper )
    2235          25 :             mxAccessible = pWrapper->CreateAccessible( this, bIsMenuBar );
    2236             :     }
    2237             : 
    2238        2481 :     return mxAccessible;
    2239             : }
    2240             : 
    2241         263 : void Menu::SetAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible )
    2242             : {
    2243         263 :     mxAccessible = rxAccessible;
    2244         263 : }
    2245             : 
    2246        3241 : Size Menu::ImplGetNativeCheckAndRadioSize( const Window* pWin, long& rCheckHeight, long& rRadioHeight ) const
    2247             : {
    2248        3241 :     long nCheckWidth = 0, nRadioWidth = 0;
    2249        3241 :     rCheckHeight = rRadioHeight = 0;
    2250             : 
    2251        3241 :     if( ! bIsMenuBar )
    2252             :     {
    2253          16 :         ImplControlValue aVal;
    2254          16 :         Rectangle aNativeBounds;
    2255          16 :         Rectangle aNativeContent;
    2256          16 :         Point tmp( 0, 0 );
    2257          16 :         Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
    2258          16 :         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
    2259             :         {
    2260           0 :             if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
    2261             :                                               ControlPart(PART_MENU_ITEM_CHECK_MARK),
    2262             :                                               aCtrlRegion,
    2263             :                                               ControlState(CTRL_STATE_ENABLED),
    2264             :                                               aVal,
    2265             :                                               OUString(),
    2266             :                                               aNativeBounds,
    2267           0 :                                               aNativeContent )
    2268             :             )
    2269             :             {
    2270           0 :                 rCheckHeight = aNativeBounds.GetHeight();
    2271           0 :                 nCheckWidth = aNativeContent.GetWidth();
    2272             :             }
    2273             :         }
    2274          16 :         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
    2275             :         {
    2276           0 :             if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
    2277             :                                               ControlPart(PART_MENU_ITEM_RADIO_MARK),
    2278             :                                               aCtrlRegion,
    2279             :                                               ControlState(CTRL_STATE_ENABLED),
    2280             :                                               aVal,
    2281             :                                               OUString(),
    2282             :                                               aNativeBounds,
    2283           0 :                                               aNativeContent )
    2284             :             )
    2285             :             {
    2286           0 :                 rRadioHeight = aNativeBounds.GetHeight();
    2287           0 :                 nRadioWidth = aNativeContent.GetWidth();
    2288             :             }
    2289          16 :         }
    2290             :     }
    2291        3241 :     return Size(std::max(nCheckWidth, nRadioWidth), std::max(rCheckHeight, rRadioHeight));
    2292             : }
    2293             : 
    2294           0 : bool Menu::ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize, long& rArrowSpacing ) const
    2295             : {
    2296           0 :     ImplControlValue aVal;
    2297           0 :     Rectangle aNativeBounds;
    2298           0 :     Rectangle aNativeContent;
    2299           0 :     Point tmp( 0, 0 );
    2300           0 :     Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
    2301           0 :     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
    2302           0 :                                         PART_MENU_SUBMENU_ARROW ) )
    2303             :         {
    2304           0 :             if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
    2305             :                                               ControlPart(PART_MENU_SUBMENU_ARROW),
    2306             :                                               aCtrlRegion,
    2307             :                                               ControlState(CTRL_STATE_ENABLED),
    2308             :                                               aVal,
    2309             :                                               OUString(),
    2310             :                                               aNativeBounds,
    2311           0 :                                               aNativeContent )
    2312             :             )
    2313             :             {
    2314             :                 Size aSize( Size ( aNativeContent.GetWidth(),
    2315           0 :                                    aNativeContent.GetHeight() ) );
    2316           0 :                 rArrowSize = aSize;
    2317           0 :                 rArrowSpacing = aNativeBounds.GetWidth() - aNativeContent.GetWidth();
    2318             : 
    2319           0 :                 return true;
    2320             :             }
    2321             :         }
    2322           0 :     return false;
    2323             : }
    2324             : 
    2325      358669 : void Menu::ImplAddDel( ImplMenuDelData& rDel )
    2326             : {
    2327             :     DBG_ASSERT( !rDel.mpMenu, "Menu::ImplAddDel(): cannot add ImplMenuDelData twice !" );
    2328      358669 :     if( !rDel.mpMenu )
    2329             :     {
    2330      358669 :         rDel.mpMenu = this;
    2331      358669 :         rDel.mpNext = mpFirstDel;
    2332      358669 :         mpFirstDel = &rDel;
    2333             :     }
    2334      358669 : }
    2335             : 
    2336      358669 : void Menu::ImplRemoveDel( ImplMenuDelData& rDel )
    2337             : {
    2338      358669 :     rDel.mpMenu = NULL;
    2339      358669 :     if ( mpFirstDel == &rDel )
    2340             :     {
    2341      358669 :         mpFirstDel = rDel.mpNext;
    2342             :     }
    2343             :     else
    2344             :     {
    2345           0 :         ImplMenuDelData* pData = mpFirstDel;
    2346           0 :         while ( pData && (pData->mpNext != &rDel) )
    2347           0 :             pData = pData->mpNext;
    2348             : 
    2349             :         DBG_ASSERT( pData, "Menu::ImplRemoveDel(): ImplMenuDelData not registered !" );
    2350           0 :         if( pData )
    2351           0 :             pData->mpNext = rDel.mpNext;
    2352             :     }
    2353      358669 : }
    2354             : 
    2355        2219 : Size Menu::ImplCalcSize( const Window* pWin )
    2356             : {
    2357             :     // | Check/Radio/Image| Text| Accel/Popup|
    2358             : 
    2359             :     // for symbols: nFontHeight x nFontHeight
    2360        2219 :     long nFontHeight = pWin->GetTextHeight();
    2361        2219 :     long nExtra = nFontHeight/4;
    2362             : 
    2363        2219 :     long nMinMenuItemHeight = nFontHeight;
    2364        2219 :     long nCheckHeight = 0, nRadioHeight = 0;
    2365        2219 :     Size aMaxSize = ImplGetNativeCheckAndRadioSize(pWin, nCheckHeight, nRadioHeight);
    2366        2219 :     if( aMaxSize.Height() > nMinMenuItemHeight )
    2367           0 :         nMinMenuItemHeight = aMaxSize.Height();
    2368             : 
    2369        2219 :     Size aMaxImgSz;
    2370             : 
    2371        2219 :     const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
    2372        2219 :     if ( rSettings.GetUseImagesInMenus() )
    2373             :     {
    2374        2219 :         if ( 16 > nMinMenuItemHeight )
    2375        2219 :             nMinMenuItemHeight = 16;
    2376       11401 :         for ( size_t i = pItemList->size(); i; )
    2377             :         {
    2378        6971 :             MenuItemData* pData = pItemList->GetDataFromPos( --i );
    2379       13942 :             if ( ImplIsVisible( i )
    2380        6979 :                && (  ( pData->eType == MENUITEM_IMAGE )
    2381        6971 :                   || ( pData->eType == MENUITEM_STRINGIMAGE )
    2382             :                   )
    2383             :                )
    2384             :             {
    2385           8 :                 Size aImgSz = pData->aImage.GetSizePixel();
    2386           8 :                 if ( aImgSz.Height() > aMaxImgSz.Height() )
    2387           8 :                     aMaxImgSz.Height() = aImgSz.Height();
    2388           8 :                 if ( aImgSz.Height() > nMinMenuItemHeight )
    2389           0 :                     nMinMenuItemHeight = aImgSz.Height();
    2390           8 :                 break;
    2391             :             }
    2392             :         }
    2393             :     }
    2394             : 
    2395        2219 :     Size aSz;
    2396        2219 :     long nCheckWidth = 0;
    2397        2219 :     long nMaxWidth = 0;
    2398             : 
    2399       11601 :     for ( size_t n = pItemList->size(); n; )
    2400             :     {
    2401        7163 :         MenuItemData* pData = pItemList->GetDataFromPos( --n );
    2402             : 
    2403        7163 :         pData->aSz.Height() = 0;
    2404        7163 :         pData->aSz.Width() = 0;
    2405             : 
    2406        7163 :         if ( ImplIsVisible( n ) )
    2407             :         {
    2408        7163 :             long nWidth = 0;
    2409             : 
    2410             :             // Separator
    2411        7163 :             if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
    2412             :             {
    2413             :                 DBG_ASSERT( !bIsMenuBar, "Separator in MenuBar ?! " );
    2414          32 :                 pData->aSz.Height() = 4;
    2415             :             }
    2416             : 
    2417             :             // Image:
    2418        7163 :             if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
    2419             :             {
    2420          84 :                 Size aImgSz = pData->aImage.GetSizePixel();
    2421          84 :                 aImgSz.Height() += 4; // add a border for native marks
    2422          84 :                 aImgSz.Width() += 4; // add a border for native marks
    2423          84 :                 if ( aImgSz.Width() > aMaxImgSz.Width() )
    2424           8 :                     aMaxImgSz.Width() = aImgSz.Width();
    2425          84 :                 if ( aImgSz.Height() > aMaxImgSz.Height() )
    2426           8 :                     aMaxImgSz.Height() = aImgSz.Height();
    2427          84 :                 if ( aImgSz.Height() > pData->aSz.Height() )
    2428          84 :                     pData->aSz.Height() = aImgSz.Height();
    2429             :             }
    2430             : 
    2431             :             // Check Buttons:
    2432        7163 :             if ( !bIsMenuBar && pData->HasCheck() )
    2433             :             {
    2434          49 :                 nCheckWidth = aMaxSize.Width();
    2435             :                 // checks / images take the same place
    2436          49 :                 if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
    2437          15 :                     nWidth += nCheckWidth + nExtra * 2;
    2438             :             }
    2439             : 
    2440             :             // Text:
    2441        7163 :             if ( (pData->eType == MENUITEM_STRING) || (pData->eType == MENUITEM_STRINGIMAGE) )
    2442             :             {
    2443        7131 :                 long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
    2444        7131 :                 long nTextHeight = pWin->GetTextHeight();
    2445             : 
    2446        7131 :                 if ( bIsMenuBar )
    2447             :                 {
    2448        6955 :                     if ( nTextHeight > pData->aSz.Height() )
    2449        6955 :                         pData->aSz.Height() = nTextHeight;
    2450             : 
    2451        6955 :                     pData->aSz.Width() = nTextWidth + 4*nExtra;
    2452        6955 :                     aSz.Width() += pData->aSz.Width();
    2453             :                 }
    2454             :                 else
    2455         176 :                     pData->aSz.Height() = std::max( std::max( nTextHeight, pData->aSz.Height() ), nMinMenuItemHeight );
    2456             : 
    2457        7131 :                 nWidth += nTextWidth;
    2458             :             }
    2459             : 
    2460             :             // Accel
    2461        7163 :             if ( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
    2462             :             {
    2463           0 :                 OUString aName = pData->aAccelKey.GetName();
    2464           0 :                 long nAccWidth = pWin->GetTextWidth( aName );
    2465           0 :                 nAccWidth += nExtra;
    2466           0 :                 nWidth += nAccWidth;
    2467             :             }
    2468             : 
    2469             :             // SubMenu?
    2470        7163 :             if ( !bIsMenuBar && pData->pSubMenu )
    2471             :             {
    2472          21 :                     if ( nFontHeight > nWidth )
    2473           0 :                         nWidth += nFontHeight;
    2474             : 
    2475          21 :                 pData->aSz.Height() = std::max( std::max( nFontHeight, pData->aSz.Height() ), nMinMenuItemHeight );
    2476             :             }
    2477             : 
    2478        7163 :             pData->aSz.Height() += EXTRAITEMHEIGHT; // little bit more distance
    2479             : 
    2480        7163 :             if ( !bIsMenuBar )
    2481         208 :                 aSz.Height() += (long)pData->aSz.Height();
    2482             : 
    2483        7163 :             if ( nWidth > nMaxWidth )
    2484        1515 :                 nMaxWidth = nWidth;
    2485             : 
    2486             :         }
    2487             :     }
    2488             : 
    2489        2219 :     if ( !bIsMenuBar )
    2490             :     {
    2491             :         // popup menus should not be wider than half the screen
    2492             :         // except on rather small screens
    2493             :         // TODO: move GetScreenNumber from SystemWindow to Window ?
    2494             :         // currently we rely on internal privileges
    2495           8 :         unsigned int nDisplayScreen = pWin->ImplGetWindowImpl()->mpFrame->maGeometry.nDisplayScreenNumber;
    2496           8 :         Rectangle aDispRect( Application::GetScreenPosSizePixel( nDisplayScreen ) );
    2497           8 :         long nScreenWidth = aDispRect.GetWidth() >= 800 ? aDispRect.GetWidth() : 800;
    2498           8 :         if( nMaxWidth > nScreenWidth/2 )
    2499           0 :             nMaxWidth = nScreenWidth/2;
    2500             : 
    2501           8 :         sal_uInt16 gfxExtra = (sal_uInt16) std::max( nExtra, 7L ); // #107710# increase space between checkmarks/images/text
    2502           8 :         nImgOrChkPos = (sal_uInt16)nExtra;
    2503           8 :         long nImgOrChkWidth = 0;
    2504           8 :         if( aMaxSize.Height() > 0 ) // NWF case
    2505           0 :             nImgOrChkWidth = aMaxSize.Height() + nExtra;
    2506             :         else // non NWF case
    2507           8 :             nImgOrChkWidth = nFontHeight/2 + gfxExtra;
    2508           8 :         nImgOrChkWidth = std::max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra );
    2509           8 :         nTextPos = (sal_uInt16)(nImgOrChkPos + nImgOrChkWidth);
    2510           8 :         nTextPos = nTextPos + gfxExtra;
    2511             : 
    2512           8 :         aSz.Width() = nTextPos + nMaxWidth + nExtra;
    2513           8 :         aSz.Width() += 4*nExtra;   // a _little_ more ...
    2514             : 
    2515           8 :         aSz.Width() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    2516           8 :         aSz.Height() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    2517             :     }
    2518             :     else
    2519             :     {
    2520        2211 :         nTextPos = (sal_uInt16)(2*nExtra);
    2521        2211 :         aSz.Height() = nFontHeight+6;
    2522             : 
    2523             :         // get menubar height from native methods if supported
    2524        2211 :         if( pWindow->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
    2525             :         {
    2526           0 :             ImplControlValue aVal;
    2527           0 :             Rectangle aNativeBounds;
    2528           0 :             Rectangle aNativeContent;
    2529           0 :             Point tmp( 0, 0 );
    2530           0 :             Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
    2531           0 :             if( pWindow->GetNativeControlRegion( ControlType(CTRL_MENUBAR),
    2532             :                                                  ControlPart(PART_ENTIRE_CONTROL),
    2533             :                                                  aCtrlRegion,
    2534             :                                                  ControlState(CTRL_STATE_ENABLED),
    2535             :                                                  aVal,
    2536             :                                                  OUString(),
    2537             :                                                  aNativeBounds,
    2538           0 :                                                  aNativeContent )
    2539             :             )
    2540             :             {
    2541           0 :                 int nNativeHeight = aNativeBounds.GetHeight();
    2542           0 :                 if( nNativeHeight > aSz.Height() )
    2543           0 :                     aSz.Height() = nNativeHeight;
    2544           0 :             }
    2545             :         }
    2546             : 
    2547             :         // account for the size of the close button, which actually is a toolbox
    2548             :         // due to NWF this is variable
    2549        2211 :         long nCloserHeight = ((MenuBarWindow*) pWindow)->MinCloseButtonSize().Height();
    2550        2211 :         if( aSz.Height() < nCloserHeight )
    2551           0 :             aSz.Height() = nCloserHeight;
    2552             :     }
    2553             : 
    2554        2219 :     if ( pLogo )
    2555           0 :         aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
    2556             : 
    2557        2219 :     return aSz;
    2558             : }
    2559             : 
    2560          12 : static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
    2561             : {
    2562          12 :     bool bNativeOk = false;
    2563          12 :     if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
    2564             :     {
    2565           0 :         ImplControlValue    aControlValue;
    2566           0 :         Rectangle           aCtrlRegion( i_rRect );
    2567           0 :         ControlState        nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
    2568             : 
    2569           0 :         aControlValue.setTristateVal( BUTTONVALUE_ON );
    2570             : 
    2571             :         bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
    2572             :                                                   aCtrlRegion, nState, aControlValue,
    2573           0 :                                                   OUString() );
    2574             :     }
    2575             : 
    2576          12 :     if( ! bNativeOk )
    2577             :     {
    2578          12 :         const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
    2579          12 :         Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
    2580          12 :         i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, true, false, 2, NULL, &aColor );
    2581             :     }
    2582          12 : }
    2583             : 
    2584        8472 : static OUString getShortenedString( const OUString& i_rLong, Window* i_pWin, long i_nMaxWidth )
    2585             : {
    2586        8472 :     sal_Int32 nPos = -1;
    2587        8472 :     OUString aNonMnem( OutputDevice::GetNonMnemonicString( i_rLong, nPos ) );
    2588        8472 :     aNonMnem = i_pWin->GetEllipsisString( aNonMnem, i_nMaxWidth, TEXT_DRAW_CENTERELLIPSIS );
    2589             :     // re-insert mnemonic
    2590        8472 :     if( nPos != -1 )
    2591             :     {
    2592        8459 :         if( nPos < aNonMnem.getLength() && i_rLong[nPos+1] == aNonMnem[nPos] )
    2593             :         {
    2594        8459 :             OUStringBuffer aBuf( i_rLong.getLength() );
    2595        8459 :             aBuf.append( aNonMnem.copy( 0, nPos) );
    2596        8459 :             aBuf.append( '~' );
    2597        8459 :             aBuf.append( aNonMnem.copy(nPos) );
    2598        8459 :             aNonMnem = aBuf.makeStringAndClear();
    2599             :         }
    2600             :     }
    2601        8472 :     return aNonMnem;
    2602             : }
    2603             : 
    2604        1022 : void Menu::ImplPaint( Window* pWin, sal_uInt16 nBorder, long nStartY, MenuItemData* pThisItemOnly, bool bHighlighted, bool bLayout, bool bRollover ) const
    2605             : {
    2606             :     // for symbols: nFontHeight x nFontHeight
    2607        1022 :     long nFontHeight = pWin->GetTextHeight();
    2608        1022 :     long nExtra = nFontHeight/4;
    2609             : 
    2610        1022 :     long nCheckHeight = 0, nRadioHeight = 0;
    2611        1022 :     ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight );
    2612             : 
    2613        1022 :     DecorationView aDecoView( pWin );
    2614        1022 :     const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
    2615             : 
    2616        1022 :     Point aTopLeft, aTmpPos;
    2617             : 
    2618        1022 :     if ( pLogo )
    2619           0 :         aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
    2620             : 
    2621        1022 :     int nOuterSpaceX = 0;
    2622        1022 :     if( !bIsMenuBar )
    2623             :     {
    2624           8 :         nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    2625           8 :         aTopLeft.X() += nOuterSpaceX;
    2626           8 :         aTopLeft.Y() += ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    2627             :     }
    2628             : 
    2629        1022 :     Size aOutSz = pWin->GetOutputSizePixel();
    2630        1022 :     size_t nCount = pItemList->size();
    2631        1022 :     if( bLayout )
    2632           2 :         mpLayoutData->m_aVisibleItemBoundRects.clear();
    2633             : 
    2634        9718 :     for ( size_t n = 0; n < nCount; n++ )
    2635             :     {
    2636        8696 :         MenuItemData* pData = pItemList->GetDataFromPos( n );
    2637        8696 :         if ( ImplIsVisible( n ) && ( !pThisItemOnly || ( pData == pThisItemOnly ) ) )
    2638             :         {
    2639        8504 :             if ( pThisItemOnly )
    2640             :             {
    2641          24 :                 if ( bIsMenuBar && bRollover )
    2642           0 :                     pWin->SetTextColor( rSettings.GetMenuBarRolloverTextColor() );
    2643          24 :                 else if ( bHighlighted )
    2644          16 :                     pWin->SetTextColor( rSettings.GetMenuHighlightTextColor() );
    2645             :             }
    2646             : 
    2647        8504 :             Point aPos( aTopLeft );
    2648        8504 :             aPos.Y() += nBorder;
    2649        8504 :             aPos.Y() += nStartY;
    2650             : 
    2651        8504 :             if ( aPos.Y() >= 0 )
    2652             :             {
    2653        8504 :                 long    nTextOffsetY = ((pData->aSz.Height()-nFontHeight)/2);
    2654        8504 :                 if( bIsMenuBar )
    2655        8296 :                     nTextOffsetY += (aOutSz.Height()-pData->aSz.Height()) / 2;
    2656        8504 :                 sal_uInt16  nTextStyle   = 0;
    2657        8504 :                 sal_uInt16  nSymbolStyle = 0;
    2658        8504 :                 sal_uInt16  nImageStyle  = 0;
    2659             : 
    2660             :                 // submenus without items are not disabled when no items are
    2661             :                 // contained. The application itself should check for this!
    2662             :                 // Otherwise it could happen entries are disabled due to
    2663             :                 // asynchronous loading
    2664        8504 :                 if ( !pData->bEnabled )
    2665             :                 {
    2666          81 :                     nTextStyle   |= TEXT_DRAW_DISABLE;
    2667          81 :                     nSymbolStyle |= SYMBOL_DRAW_DISABLE;
    2668          81 :                     nImageStyle  |= IMAGE_DRAW_DISABLE;
    2669             :                 }
    2670             : 
    2671             :                 // Separator
    2672        8504 :                 if ( !bLayout && !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
    2673             :                 {
    2674          28 :                     bool bNativeOk = false;
    2675          28 :                     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
    2676          28 :                                                         PART_MENU_SEPARATOR ) )
    2677             :                     {
    2678           0 :                         ControlState nState = 0;
    2679           0 :                         if ( pData->bEnabled )
    2680           0 :                             nState |= CTRL_STATE_ENABLED;
    2681           0 :                         if ( bHighlighted )
    2682           0 :                             nState |= CTRL_STATE_SELECTED;
    2683           0 :                         Size aSz( pData->aSz );
    2684           0 :                         aSz.Width() = aOutSz.Width() - 2*nOuterSpaceX;
    2685           0 :                         Rectangle aItemRect( aPos, aSz );
    2686           0 :                         MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
    2687             :                         bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
    2688             :                                                              aItemRect,
    2689             :                                                              nState,
    2690             :                                                              aVal,
    2691           0 :                                                              OUString() );
    2692             :                     }
    2693          28 :                     if( ! bNativeOk )
    2694             :                     {
    2695          28 :                         aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height()-2)/2);
    2696          28 :                         aTmpPos.X() = aPos.X() + 2 + nOuterSpaceX;
    2697          28 :                         pWin->SetLineColor( rSettings.GetShadowColor() );
    2698          28 :                         pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpaceX, aTmpPos.Y() ) );
    2699          28 :                         aTmpPos.Y()++;
    2700          28 :                         pWin->SetLineColor( rSettings.GetLightColor() );
    2701          28 :                         pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpaceX, aTmpPos.Y() ) );
    2702          28 :                         pWin->SetLineColor();
    2703             :                     }
    2704             :                 }
    2705             : 
    2706        8504 :                 Rectangle aOuterCheckRect( Point( aPos.X()+nImgOrChkPos, aPos.Y() ), Size( pData->aSz.Height(), pData->aSz.Height() ) );
    2707        8504 :                 aOuterCheckRect.Left()      += 1;
    2708        8504 :                 aOuterCheckRect.Right()     -= 1;
    2709        8504 :                 aOuterCheckRect.Top()       += 1;
    2710        8504 :                 aOuterCheckRect.Bottom()    -= 1;
    2711             : 
    2712             :                 // CheckMark
    2713        8504 :                 if ( !bLayout && !bIsMenuBar && pData->HasCheck() )
    2714             :                 {
    2715             :                     // draw selection transparent marker if checked
    2716             :                     // onto that either a checkmark or the item image
    2717             :                     // will be painted
    2718             :                     // however do not do this if native checks will be painted since
    2719             :                     // the selection color too often does not fit the theme's check and/or radio
    2720             : 
    2721          36 :                     if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
    2722             :                     {
    2723          10 :                         if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
    2724          10 :                                                              (pData->nBits & MIB_RADIOCHECK)
    2725             :                                                              ? PART_MENU_ITEM_CHECK_MARK
    2726          10 :                                                              : PART_MENU_ITEM_RADIO_MARK ) )
    2727             :                         {
    2728           0 :                             ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK)
    2729             :                                                  ? PART_MENU_ITEM_RADIO_MARK
    2730           0 :                                                  : PART_MENU_ITEM_CHECK_MARK);
    2731             : 
    2732           0 :                             ControlState nState = 0;
    2733             : 
    2734           0 :                             if ( pData->bChecked )
    2735           0 :                                 nState |= CTRL_STATE_PRESSED;
    2736             : 
    2737           0 :                             if ( pData->bEnabled )
    2738           0 :                                 nState |= CTRL_STATE_ENABLED;
    2739             : 
    2740           0 :                             if ( bHighlighted )
    2741           0 :                                 nState |= CTRL_STATE_SELECTED;
    2742             : 
    2743           0 :                             long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
    2744           0 :                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
    2745           0 :                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
    2746             : 
    2747           0 :                             Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
    2748           0 :                             Size aSz( pData->aSz );
    2749           0 :                             aSz.Width() = aOutSz.Width() - 2*nOuterSpaceX;
    2750           0 :                             Rectangle aItemRect( aPos, aSz );
    2751           0 :                             MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
    2752             :                             pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart,
    2753             :                                                      aCheckRect,
    2754             :                                                      nState,
    2755             :                                                      aVal,
    2756           0 :                                                      OUString() );
    2757             :                         }
    2758          10 :                         else if ( pData->bChecked ) // by default do nothing for unchecked items
    2759             :                         {
    2760           8 :                             ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
    2761             : 
    2762             :                             SymbolType eSymbol;
    2763           8 :                             Size aSymbolSize;
    2764           8 :                             if ( pData->nBits & MIB_RADIOCHECK )
    2765             :                             {
    2766           0 :                                 eSymbol = SYMBOL_RADIOCHECKMARK;
    2767           0 :                                 aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
    2768             :                             }
    2769             :                             else
    2770             :                             {
    2771           8 :                                 eSymbol = SYMBOL_CHECKMARK;
    2772           8 :                                 aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
    2773             :                             }
    2774           8 :                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
    2775           8 :                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
    2776           8 :                             Rectangle aRect( aTmpPos, aSymbolSize );
    2777           8 :                             aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle );
    2778             :                         }
    2779             :                     }
    2780             :                 }
    2781             : 
    2782             :                 // Image:
    2783        8504 :                 if ( !bLayout && !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
    2784             :                 {
    2785             :                     // Don't render an image for a check thing
    2786          76 :                     if( pData->bChecked )
    2787           4 :                         ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
    2788          76 :                     aTmpPos = aOuterCheckRect.TopLeft();
    2789          76 :                     aTmpPos.X() += (aOuterCheckRect.GetWidth()-pData->aImage.GetSizePixel().Width())/2;
    2790          76 :                     aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pData->aImage.GetSizePixel().Height())/2;
    2791          76 :                     pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle );
    2792             :                 }
    2793             : 
    2794             :                 // Text:
    2795        8504 :                 if ( ( pData->eType == MENUITEM_STRING ) || ( pData->eType == MENUITEM_STRINGIMAGE ) )
    2796             :                 {
    2797        8472 :                     aTmpPos.X() = aPos.X() + nTextPos;
    2798        8472 :                     aTmpPos.Y() = aPos.Y();
    2799        8472 :                     aTmpPos.Y() += nTextOffsetY;
    2800        8472 :                     sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
    2801        8472 :                     if ( pData->bIsTemporary )
    2802           0 :                         nStyle |= TEXT_DRAW_DISABLE;
    2803        8472 :                     MetricVector* pVector = bLayout ? &mpLayoutData->m_aUnicodeBoundRects : NULL;
    2804        8472 :                     OUString* pDisplayText = bLayout ? &mpLayoutData->m_aDisplayText : NULL;
    2805        8472 :                     if( bLayout )
    2806             :                     {
    2807          26 :                         mpLayoutData->m_aLineIndices.push_back( mpLayoutData->m_aDisplayText.getLength() );
    2808          26 :                         mpLayoutData->m_aLineItemIds.push_back( pData->nId );
    2809          26 :                         mpLayoutData->m_aLineItemPositions.push_back( n );
    2810             :                     }
    2811             :                     // #i47946# with NWF painted menus the background is transparent
    2812             :                     // since DrawCtrlText can depend on the background (e.g. for
    2813             :                     // TEXT_DRAW_DISABLE), temporarily set a background which
    2814             :                     // hopefully matches the NWF background since it is read
    2815             :                     // from the system style settings
    2816        8472 :                     bool bSetTmpBackground = !pWin->IsBackground() && pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL );
    2817        8472 :                     if( bSetTmpBackground )
    2818             :                     {
    2819             :                         Color aBg = bIsMenuBar ?
    2820           0 :                             pWin->GetSettings().GetStyleSettings().GetMenuBarColor() :
    2821           0 :                             pWin->GetSettings().GetStyleSettings().GetMenuColor();
    2822           0 :                         pWin->SetBackground( Wallpaper( aBg ) );
    2823             :                     }
    2824             :                     // how much space is there for the text ?
    2825        8472 :                     long nMaxItemTextWidth = aOutSz.Width() - aTmpPos.X() - nExtra - nOuterSpaceX;
    2826        8472 :                     if( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
    2827             :                     {
    2828           0 :                         OUString aAccText = pData->aAccelKey.GetName();
    2829           0 :                         nMaxItemTextWidth -= pWin->GetTextWidth( aAccText ) + 3*nExtra;
    2830             :                     }
    2831        8472 :                     if( !bIsMenuBar && pData->pSubMenu )
    2832             :                     {
    2833          21 :                         nMaxItemTextWidth -= nFontHeight - nExtra;
    2834             :                     }
    2835        8472 :                     OUString aItemText( getShortenedString( pData->aText, pWin, nMaxItemTextWidth ) );
    2836        8472 :                     pWin->DrawCtrlText( aTmpPos, aItemText, 0, aItemText.getLength(), nStyle, pVector, pDisplayText );
    2837        8472 :                     if( bSetTmpBackground )
    2838           0 :                         pWin->SetBackground();
    2839             :                 }
    2840             : 
    2841             :                 // Accel
    2842        8504 :                 if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
    2843             :                 {
    2844           0 :                     OUString aAccText = pData->aAccelKey.GetName();
    2845           0 :                     aTmpPos.X() = aOutSz.Width() - pWin->GetTextWidth( aAccText );
    2846           0 :                     aTmpPos.X() -= 4*nExtra;
    2847             : 
    2848           0 :                     aTmpPos.X() -= nOuterSpaceX;
    2849           0 :                     aTmpPos.Y() = aPos.Y();
    2850           0 :                     aTmpPos.Y() += nTextOffsetY;
    2851           0 :                     pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.getLength(), nTextStyle );
    2852             :                 }
    2853             : 
    2854             :                 // SubMenu?
    2855        8504 :                 if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
    2856             :                 {
    2857          19 :                     bool bNativeOk = false;
    2858          19 :                     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
    2859          19 :                                                         PART_MENU_SUBMENU_ARROW ) )
    2860             :                     {
    2861           0 :                         ControlState nState = 0;
    2862           0 :                         Size aTmpSz( 0, 0 );
    2863           0 :                         long aSpacing = 0;
    2864             : 
    2865           0 :                         if( !ImplGetNativeSubmenuArrowSize( pWin,
    2866           0 :                                                             aTmpSz, aSpacing ) )
    2867             :                         {
    2868           0 :                             aTmpSz = Size( nFontHeight, nFontHeight );
    2869           0 :                             aSpacing = nOuterSpaceX;
    2870             :                         }
    2871             : 
    2872           0 :                         if ( pData->bEnabled )
    2873           0 :                             nState |= CTRL_STATE_ENABLED;
    2874           0 :                         if ( bHighlighted )
    2875           0 :                             nState |= CTRL_STATE_SELECTED;
    2876             : 
    2877           0 :                         aTmpPos.X() = aOutSz.Width() - aTmpSz.Width() - aSpacing - nOuterSpaceX;
    2878           0 :                         aTmpPos.Y() = aPos.Y() + ( pData->aSz.Height() - aTmpSz.Height() ) / 2;
    2879           0 :                         aTmpPos.Y() += nExtra/2;
    2880             : 
    2881           0 :                         Rectangle aItemRect( aTmpPos, aTmpSz );
    2882           0 :                         MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
    2883             :                         bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP,
    2884             :                                                              PART_MENU_SUBMENU_ARROW,
    2885             :                                                              aItemRect,
    2886             :                                                              nState,
    2887             :                                                              aVal,
    2888           0 :                                                              OUString() );
    2889             :                     }
    2890          19 :                     if( ! bNativeOk )
    2891             :                     {
    2892          19 :                         aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpaceX;
    2893          19 :                         aTmpPos.Y() = aPos.Y();
    2894          19 :                         aTmpPos.Y() += nExtra/2;
    2895          19 :                         aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
    2896          19 :                         if ( pData->nBits & MIB_POPUPSELECT )
    2897             :                         {
    2898           0 :                             pWin->SetTextColor( rSettings.GetMenuTextColor() );
    2899           0 :                             Point aTmpPos2( aPos );
    2900           0 :                             aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
    2901             :                             aDecoView.DrawFrame(
    2902           0 :                                 Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
    2903             :                         }
    2904             :                         aDecoView.DrawSymbol(
    2905             :                             Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
    2906          19 :                             SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
    2907             :                     }
    2908             :                 }
    2909             : 
    2910        8504 :                 if ( pThisItemOnly && bHighlighted )
    2911             :                 {
    2912             :                     // This restores the normal menu or menu bar text
    2913             :                     // color for when it is no longer highlighted.
    2914          16 :                     if ( bIsMenuBar )
    2915          16 :                         pWin->SetTextColor( rSettings.GetMenuBarTextColor() );
    2916             :                     else
    2917           0 :                         pWin->SetTextColor( rSettings.GetMenuTextColor() );
    2918             :                 }
    2919             :             }
    2920        8504 :             if( bLayout )
    2921             :             {
    2922          30 :                 if ( !bIsMenuBar )
    2923          21 :                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, Size( aOutSz.Width(), pData->aSz.Height() ) );
    2924             :                 else
    2925           9 :                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, pData->aSz );
    2926             :             }
    2927             :         }
    2928             : 
    2929        8696 :         if ( !bIsMenuBar )
    2930             :         {
    2931         208 :             aTopLeft.Y() += pData->aSz.Height();
    2932             :         }
    2933             :         else
    2934             :         {
    2935        8488 :             aTopLeft.X() += pData->aSz.Width();
    2936             :         }
    2937             :     }
    2938             : 
    2939        1022 :     if ( !bLayout && !pThisItemOnly && pLogo )
    2940             :     {
    2941           0 :         Size aLogoSz = pLogo->aBitmap.GetSizePixel();
    2942             : 
    2943           0 :         Rectangle aRect( Point( 0, 0 ), Point( aLogoSz.Width()-1, aOutSz.Height() ) );
    2944           0 :         if ( pWin->GetColorCount() >= 256 )
    2945             :         {
    2946           0 :             Gradient aGrad( GradientStyle_LINEAR, pLogo->aStartColor, pLogo->aEndColor );
    2947           0 :             aGrad.SetAngle( 1800 );
    2948           0 :             aGrad.SetBorder( 15 );
    2949           0 :             pWin->DrawGradient( aRect, aGrad );
    2950             :         }
    2951             :         else
    2952             :         {
    2953           0 :             pWin->SetFillColor( pLogo->aStartColor );
    2954           0 :             pWin->DrawRect( aRect );
    2955             :         }
    2956             : 
    2957           0 :         Point aLogoPos( 0, aOutSz.Height() - aLogoSz.Height() );
    2958           0 :         pLogo->aBitmap.Draw( pWin, aLogoPos );
    2959             :     }
    2960        1022 : }
    2961             : 
    2962          50 : Menu* Menu::ImplGetStartMenu()
    2963             : {
    2964          50 :     Menu* pStart = this;
    2965         108 :     while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
    2966           8 :         pStart = pStart->pStartedFrom;
    2967          50 :     return pStart;
    2968             : }
    2969             : 
    2970          26 : void Menu::ImplCallHighlight(sal_uInt16 nItem)
    2971             : {
    2972          26 :     ImplMenuDelData aDelData( this );
    2973             : 
    2974          26 :     nSelectedId = 0;
    2975          26 :     MenuItemData* pData = pItemList->GetDataFromPos(nItem);
    2976          26 :     if ( pData )
    2977          10 :         nSelectedId = pData->nId;
    2978          26 :     ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT, GetItemPos( GetCurItemId() ) );
    2979             : 
    2980          26 :     if( !aDelData.isDeleted() )
    2981             :     {
    2982          26 :         Highlight();
    2983          26 :         nSelectedId = 0;
    2984          26 :     }
    2985          26 : }
    2986             : 
    2987           0 : IMPL_LINK_NOARG(Menu, ImplCallSelect)
    2988             : {
    2989           0 :     nEventId = 0;
    2990           0 :     Select();
    2991           0 :     return 0;
    2992             : }
    2993             : 
    2994           0 : Menu* Menu::ImplFindSelectMenu()
    2995             : {
    2996           0 :     Menu* pSelMenu = nEventId ? this : NULL;
    2997             : 
    2998           0 :     for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
    2999             :     {
    3000           0 :         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
    3001             : 
    3002           0 :         if ( pData->pSubMenu )
    3003           0 :             pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
    3004             :     }
    3005             : 
    3006           0 :     return pSelMenu;
    3007             : }
    3008             : 
    3009           0 : Menu* Menu::ImplFindMenu( sal_uInt16 nItemId )
    3010             : {
    3011           0 :     Menu* pSelMenu = NULL;
    3012             : 
    3013           0 :     for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
    3014             :     {
    3015           0 :         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
    3016             : 
    3017           0 :         if( pData->nId == nItemId )
    3018           0 :             pSelMenu = this;
    3019           0 :         else if ( pData->pSubMenu )
    3020           0 :             pSelMenu = pData->pSubMenu->ImplFindMenu( nItemId );
    3021             :     }
    3022             : 
    3023           0 :     return pSelMenu;
    3024             : }
    3025             : 
    3026           5 : void Menu::RemoveDisabledEntries( bool bCheckPopups, bool bRemoveEmptyPopups )
    3027             : {
    3028          31 :     for ( sal_uInt16 n = 0; n < GetItemCount(); n++ )
    3029             :     {
    3030          26 :         bool bRemove = false;
    3031          26 :         MenuItemData* pItem = pItemList->GetDataFromPos( n );
    3032          26 :         if ( pItem->eType == MENUITEM_SEPARATOR )
    3033             :         {
    3034           2 :             if ( !n || ( GetItemType( n-1 ) == MENUITEM_SEPARATOR ) )
    3035           0 :                 bRemove = true;
    3036             :         }
    3037             :         else
    3038          24 :             bRemove = !pItem->bEnabled;
    3039             : 
    3040          26 :         if ( bCheckPopups && pItem->pSubMenu )
    3041             :         {
    3042           4 :             pItem->pSubMenu->RemoveDisabledEntries( true );
    3043           4 :             if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
    3044           1 :                 bRemove = true;
    3045             :         }
    3046             : 
    3047          26 :         if ( bRemove )
    3048           4 :             RemoveItem( n-- );
    3049             :     }
    3050             : 
    3051           5 :     if ( GetItemCount() )
    3052             :     {
    3053           4 :         sal_uInt16 nLast = GetItemCount() - 1;
    3054           4 :         MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
    3055           4 :         if ( pItem->eType == MENUITEM_SEPARATOR )
    3056           0 :             RemoveItem( nLast );
    3057             :     }
    3058           5 :     delete mpLayoutData, mpLayoutData = NULL;
    3059           5 : }
    3060             : 
    3061           0 : bool Menu::HasValidEntries( bool bCheckPopups )
    3062             : {
    3063           0 :     bool bValidEntries = false;
    3064           0 :     sal_uInt16 nCount = GetItemCount();
    3065           0 :     for ( sal_uInt16 n = 0; !bValidEntries && ( n < nCount ); n++ )
    3066             :     {
    3067           0 :         MenuItemData* pItem = pItemList->GetDataFromPos( n );
    3068           0 :         if ( pItem->bEnabled && ( pItem->eType != MENUITEM_SEPARATOR ) )
    3069             :         {
    3070           0 :             if ( bCheckPopups && pItem->pSubMenu )
    3071           0 :                 bValidEntries = pItem->pSubMenu->HasValidEntries( true );
    3072             :             else
    3073           0 :                 bValidEntries = true;
    3074             :         }
    3075             :     }
    3076           0 :     return bValidEntries;
    3077             : }
    3078             : 
    3079        4818 : void Menu::ImplKillLayoutData() const
    3080             : {
    3081        4818 :     delete mpLayoutData, mpLayoutData = NULL;
    3082        4818 : }
    3083             : 
    3084           2 : void Menu::ImplFillLayoutData() const
    3085             : {
    3086           2 :     if( pWindow && pWindow->IsReallyVisible() )
    3087             :     {
    3088           2 :         mpLayoutData = new MenuLayoutData();
    3089           2 :         if( bIsMenuBar )
    3090             :         {
    3091           1 :             ImplPaint( pWindow, 0, 0, 0, false, true );
    3092             :         }
    3093             :         else
    3094             :         {
    3095           1 :             MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
    3096           1 :             ImplPaint( pWindow, pFloat->nScrollerHeight, pFloat->ImplGetStartY(), 0, false, true );
    3097             :         }
    3098             :     }
    3099           2 : }
    3100             : 
    3101           0 : Rectangle Menu::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
    3102             : {
    3103           0 :     long nItemIndex = -1;
    3104           0 :     if( ! mpLayoutData )
    3105           0 :         ImplFillLayoutData();
    3106           0 :     if( mpLayoutData )
    3107             :     {
    3108           0 :         for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
    3109             :         {
    3110           0 :             if( mpLayoutData->m_aLineItemIds[i] == nItemID )
    3111             :             {
    3112           0 :                 nItemIndex = mpLayoutData->m_aLineIndices[i];
    3113           0 :                 break;
    3114             :             }
    3115             :         }
    3116             :     }
    3117           0 :     return (mpLayoutData && nItemIndex != -1) ? mpLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
    3118             : }
    3119             : 
    3120           0 : long Menu::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
    3121             : {
    3122           0 :     long nIndex = -1;
    3123           0 :     rItemID = 0;
    3124           0 :     if( ! mpLayoutData )
    3125           0 :         ImplFillLayoutData();
    3126           0 :     if( mpLayoutData )
    3127             :     {
    3128           0 :         nIndex = mpLayoutData->GetIndexForPoint( rPoint );
    3129           0 :         for( size_t i = 0; i < mpLayoutData->m_aLineIndices.size(); i++ )
    3130             :         {
    3131           0 :             if( mpLayoutData->m_aLineIndices[i] <= nIndex &&
    3132           0 :                 (i == mpLayoutData->m_aLineIndices.size()-1 || mpLayoutData->m_aLineIndices[i+1] > nIndex) )
    3133             :             {
    3134             :                 // make index relative to item
    3135           0 :                 nIndex -= mpLayoutData->m_aLineIndices[i];
    3136           0 :                 rItemID = mpLayoutData->m_aLineItemIds[i];
    3137           0 :                 break;
    3138             :             }
    3139             :         }
    3140             :     }
    3141           0 :     return nIndex;
    3142             : }
    3143             : 
    3144        1552 : Rectangle Menu::GetBoundingRectangle( sal_uInt16 nPos ) const
    3145             : {
    3146        1552 :     Rectangle aRet;
    3147             : 
    3148        1552 :     if( ! mpLayoutData )
    3149           2 :         ImplFillLayoutData();
    3150        1552 :     if( mpLayoutData )
    3151             :     {
    3152        1552 :         std::map< sal_uInt16, Rectangle >::const_iterator it = mpLayoutData->m_aVisibleItemBoundRects.find( nPos );
    3153        1552 :         if( it != mpLayoutData->m_aVisibleItemBoundRects.end() )
    3154        1552 :             aRet = it->second;
    3155             :     }
    3156        1552 :     return aRet;
    3157             : }
    3158             : 
    3159           0 : void Menu::SetAccessibleName( sal_uInt16 nItemId, const OUString& rStr )
    3160             : {
    3161             :     size_t        nPos;
    3162           0 :     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
    3163             : 
    3164           0 :     if ( pData && !rStr.equals( pData->aAccessibleName ) )
    3165             :     {
    3166           0 :         pData->aAccessibleName = rStr;
    3167           0 :         ImplCallEventListeners( VCLEVENT_MENU_ACCESSIBLENAMECHANGED, nPos );
    3168             :     }
    3169           0 : }
    3170             : 
    3171        1964 : OUString Menu::GetAccessibleName( sal_uInt16 nItemId ) const
    3172             : {
    3173        1964 :     MenuItemData* pData = pItemList->GetData( nItemId );
    3174             : 
    3175        1964 :     if ( pData )
    3176        1964 :         return pData->aAccessibleName;
    3177             : 
    3178           0 :     return OUString();
    3179             : }
    3180             : 
    3181       47080 : void Menu::ImplSetSalMenu( SalMenu *pSalMenu )
    3182             : {
    3183       47080 :     if( mpSalMenu )
    3184           0 :         ImplGetSVData()->mpDefInst->DestroyMenu( mpSalMenu );
    3185       47080 :     mpSalMenu = pSalMenu;
    3186       47080 : }
    3187             : 
    3188           0 : bool Menu::GetSystemMenuData( SystemMenuData* pData ) const
    3189             : {
    3190           0 :     Menu* pMenu = (Menu*)this;
    3191           0 :     if( pData && pMenu->ImplGetSalMenu() )
    3192             :     {
    3193           0 :         pMenu->ImplGetSalMenu()->GetSystemMenuData( pData );
    3194           0 :         return true;
    3195             :     }
    3196             :     else
    3197           0 :         return false;
    3198             : }
    3199             : 
    3200        7222 : bool Menu::IsHighlighted( sal_uInt16 nItemPos ) const
    3201             : {
    3202        7222 :     bool bRet = false;
    3203             : 
    3204        7222 :     if( pWindow )
    3205             :     {
    3206         298 :         if( bIsMenuBar )
    3207         230 :             bRet = ( nItemPos == static_cast< MenuBarWindow * > (pWindow)->GetHighlightedItem() );
    3208             :         else
    3209          68 :             bRet = ( nItemPos == static_cast< MenuFloatingWindow * > (pWindow)->GetHighlightedItem() );
    3210             :     }
    3211             : 
    3212        7222 :     return bRet;
    3213             : }
    3214             : 
    3215           0 : void Menu::HighlightItem( sal_uInt16 nItemPos )
    3216             : {
    3217           0 :     if ( pWindow )
    3218             :     {
    3219           0 :         if ( bIsMenuBar )
    3220             :         {
    3221           0 :             MenuBarWindow* pMenuWin = static_cast< MenuBarWindow* >( pWindow );
    3222           0 :             pMenuWin->SetAutoPopup( false );
    3223           0 :             pMenuWin->ChangeHighlightItem( nItemPos, false );
    3224             :         }
    3225             :         else
    3226             :         {
    3227           0 :             static_cast< MenuFloatingWindow* >( pWindow )->ChangeHighlightItem( nItemPos, false );
    3228             :         }
    3229             :     }
    3230           0 : }
    3231             : 
    3232             : // - MenuBar -
    3233             : 
    3234        2042 : MenuBar::MenuBar() : Menu( true )
    3235             : {
    3236        2042 :     mbDisplayable       = true;
    3237        2042 :     mbCloserVisible     = false;
    3238        2042 :     mbFloatBtnVisible   = false;
    3239        2042 :     mbHideBtnVisible    = false;
    3240        2042 : }
    3241             : 
    3242           0 : MenuBar::MenuBar( const MenuBar& rMenu ) : Menu( true )
    3243             : {
    3244           0 :     mbDisplayable       = true;
    3245           0 :     mbCloserVisible     = false;
    3246           0 :     mbFloatBtnVisible   = false;
    3247           0 :     mbHideBtnVisible    = false;
    3248           0 :     *this               = rMenu;
    3249           0 :     bIsMenuBar          = true;
    3250           0 : }
    3251             : 
    3252        6099 : MenuBar::~MenuBar()
    3253             : {
    3254        2033 :     ImplDestroy( this, true );
    3255        4066 : }
    3256             : 
    3257        2835 : void MenuBar::ShowCloser( bool bShow )
    3258             : {
    3259        2835 :     ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
    3260        2835 : }
    3261             : 
    3262        2835 : void MenuBar::ShowButtons( bool bClose, bool bFloat, bool bHide )
    3263             : {
    3264        3645 :     if ( (bClose != mbCloserVisible)    ||
    3265        1620 :          (bFloat != mbFloatBtnVisible)  ||
    3266         810 :          (bHide  != mbHideBtnVisible) )
    3267             :     {
    3268        2025 :         mbCloserVisible     = bClose;
    3269        2025 :         mbFloatBtnVisible   = bFloat;
    3270        2025 :         mbHideBtnVisible    = bHide;
    3271        2025 :         if ( ImplGetWindow() )
    3272        2025 :             ((MenuBarWindow*)ImplGetWindow())->ShowButtons( bClose, bFloat, bHide );
    3273             :     }
    3274        2835 : }
    3275             : 
    3276        2040 : void MenuBar::SetDisplayable( bool bDisplayable )
    3277             : {
    3278        2040 :     if( bDisplayable != mbDisplayable )
    3279             :     {
    3280           0 :         mbDisplayable = bDisplayable;
    3281           0 :         MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
    3282           0 :         if( pMenuWin )
    3283           0 :             pMenuWin->ImplLayoutChanged();
    3284             :     }
    3285        2040 : }
    3286             : 
    3287        2043 : Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
    3288             : {
    3289        2043 :     if ( !pWindow )
    3290        2042 :         pWindow = new MenuBarWindow( pParent );
    3291             : 
    3292        2043 :     pMenu->pStartedFrom = 0;
    3293        2043 :     pMenu->pWindow = pWindow;
    3294        2043 :     ((MenuBarWindow*)pWindow)->SetMenu( pMenu );
    3295        2043 :     long nHeight = pMenu->ImplCalcSize( pWindow ).Height();
    3296             : 
    3297             :     // depending on the native implementation or the displayable flag
    3298             :     // the menubar windows is supressed (ie, height=0)
    3299        4086 :     if( !((MenuBar*) pMenu)->IsDisplayable() ||
    3300        2043 :         ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
    3301           0 :         nHeight = 0;
    3302             : 
    3303        2043 :     pWindow->setPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
    3304        2043 :     return pWindow;
    3305             : }
    3306             : 
    3307        4068 : void MenuBar::ImplDestroy( MenuBar* pMenu, bool bDelete )
    3308             : {
    3309        4068 :     MenuBarWindow* pWindow = (MenuBarWindow*) pMenu->ImplGetWindow();
    3310        4068 :     if ( pWindow && bDelete )
    3311             :     {
    3312        2034 :         pWindow->KillActivePopup();
    3313        2034 :         delete pWindow;
    3314             :     }
    3315        4068 :     pMenu->pWindow = NULL;
    3316        4068 : }
    3317             : 
    3318           0 : bool MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
    3319             : {
    3320           0 :     bool bDone = false;
    3321             : 
    3322             :     // No keyboard processing when system handles the menu or our menubar is invisible
    3323           0 :     if( !IsDisplayable() ||
    3324           0 :         ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
    3325           0 :         return bDone;
    3326             : 
    3327             :     // check for enabled, if this method is called from another window...
    3328           0 :     Window* pWin = ImplGetWindow();
    3329           0 :     if ( pWin && pWin->IsEnabled() && pWin->IsInputEnabled()  && ! pWin->IsInModalMode() )
    3330           0 :         bDone = ((MenuBarWindow*)pWin)->ImplHandleKeyEvent( rKEvent, bFromMenu );
    3331           0 :     return bDone;
    3332             : }
    3333             : 
    3334           8 : void MenuBar::SelectEntry( sal_uInt16 nId )
    3335             : {
    3336           8 :     MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
    3337             : 
    3338           8 :     if( pMenuWin )
    3339             :     {
    3340           8 :         pMenuWin->GrabFocus();
    3341           8 :         nId = GetItemPos( nId );
    3342             : 
    3343             :         // #99705# popup the selected menu
    3344           8 :         pMenuWin->SetAutoPopup( true );
    3345           8 :         if( ITEMPOS_INVALID != pMenuWin->nHighlightedItem )
    3346             :         {
    3347           8 :             pMenuWin->KillActivePopup();
    3348           8 :             pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, false );
    3349             :         }
    3350           8 :         if( nId != ITEMPOS_INVALID )
    3351           8 :             pMenuWin->ChangeHighlightItem( nId, false );
    3352             :     }
    3353           8 : }
    3354             : 
    3355             : // handler for native menu selection and command events
    3356             : 
    3357           0 : bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
    3358             : {
    3359           0 :     if( pMenu )
    3360             :     {
    3361           0 :         ImplMenuDelData aDelData( this );
    3362             : 
    3363           0 :         pMenu->pStartedFrom = (Menu*)this;
    3364           0 :         pMenu->bInCallback = true;
    3365           0 :         pMenu->Activate();
    3366             : 
    3367           0 :         if( !aDelData.isDeleted() )
    3368           0 :             pMenu->bInCallback = false;
    3369             :     }
    3370           0 :     return true;
    3371             : }
    3372             : 
    3373           0 : bool MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
    3374             : {
    3375           0 :     if( pMenu )
    3376             :     {
    3377           0 :         ImplMenuDelData aDelData( this );
    3378             : 
    3379           0 :         pMenu->pStartedFrom = (Menu*)this;
    3380           0 :         pMenu->bInCallback = true;
    3381           0 :         pMenu->Deactivate();
    3382           0 :         if( !aDelData.isDeleted() )
    3383           0 :             pMenu->bInCallback = false;
    3384             :     }
    3385           0 :     return true;
    3386             : }
    3387             : 
    3388           0 : bool MenuBar::HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nHighlightEventId ) const
    3389             : {
    3390           0 :     if( !pMenu )
    3391           0 :         pMenu = ((Menu*) this)->ImplFindMenu( nHighlightEventId );
    3392           0 :     if( pMenu )
    3393             :     {
    3394           0 :         ImplMenuDelData aDelData( pMenu );
    3395             : 
    3396           0 :         if( mnHighlightedItemPos != ITEMPOS_INVALID )
    3397           0 :             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, mnHighlightedItemPos );
    3398             : 
    3399           0 :         if( !aDelData.isDeleted() )
    3400             :         {
    3401           0 :             pMenu->mnHighlightedItemPos = pMenu->GetItemPos( nHighlightEventId );
    3402           0 :             pMenu->nSelectedId = nHighlightEventId;
    3403           0 :             pMenu->pStartedFrom = (Menu*)this;
    3404           0 :             pMenu->ImplCallHighlight( pMenu->mnHighlightedItemPos );
    3405             :         }
    3406           0 :         return true;
    3407             :     }
    3408             :     else
    3409           0 :         return false;
    3410             : }
    3411             : 
    3412           0 : bool MenuBar::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
    3413             : {
    3414           0 :     if( !pMenu )
    3415           0 :         pMenu = ((Menu*) this)->ImplFindMenu( nCommandEventId );
    3416           0 :     if( pMenu )
    3417             :     {
    3418           0 :         pMenu->nSelectedId = nCommandEventId;
    3419           0 :         pMenu->pStartedFrom = (Menu*)this;
    3420           0 :         pMenu->ImplSelect();
    3421           0 :         return true;
    3422             :     }
    3423             :     else
    3424           0 :         return false;
    3425             : }
    3426             : 
    3427           0 : sal_uInt16 MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const OUString& i_rToolTip, sal_uInt16 i_nPos )
    3428             : {
    3429           0 :     return pWindow ? static_cast<MenuBarWindow*>(pWindow)->AddMenuBarButton( i_rImage, i_rLink, i_rToolTip, i_nPos ) : 0;
    3430             : }
    3431             : 
    3432           0 : void MenuBar::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
    3433             : {
    3434           0 :     if( pWindow )
    3435           0 :         static_cast<MenuBarWindow*>(pWindow)->SetMenuBarButtonHighlightHdl( nId, rLink );
    3436           0 : }
    3437             : 
    3438           0 : Rectangle MenuBar::GetMenuBarButtonRectPixel( sal_uInt16 nId )
    3439             : {
    3440           0 :     return pWindow ? static_cast<MenuBarWindow*>(pWindow)->GetMenuBarButtonRectPixel( nId ) : Rectangle();
    3441             : }
    3442             : 
    3443           0 : void MenuBar::RemoveMenuBarButton( sal_uInt16 nId )
    3444             : {
    3445           0 :     if( pWindow )
    3446           0 :         static_cast<MenuBarWindow*>(pWindow)->RemoveMenuBarButton( nId );
    3447           0 : }
    3448             : 
    3449           0 : bool MenuBar::HandleMenuButtonEvent( Menu *, sal_uInt16 i_nButtonId ) const
    3450             : {
    3451           0 :     return static_cast<MenuBarWindow*>(pWindow)->HandleMenuButtonEvent( i_nButtonId );
    3452             : }
    3453             : 
    3454             : // bool PopupMenu::bAnyPopupInExecute = false;
    3455             : 
    3456       44070 : PopupMenu::PopupMenu()
    3457             : {
    3458       44070 :     pRefAutoSubMenu = NULL;
    3459       44070 : }
    3460             : 
    3461        1011 : PopupMenu::PopupMenu( const ResId& rResId )
    3462             : {
    3463        1011 :     pRefAutoSubMenu = NULL;
    3464        1011 :     ImplLoadRes( rResId );
    3465        1011 : }
    3466             : 
    3467           0 : PopupMenu::PopupMenu( const PopupMenu& rMenu ) : Menu()
    3468             : {
    3469           0 :     pRefAutoSubMenu = NULL;
    3470           0 :     *this = rMenu;
    3471           0 : }
    3472             : 
    3473      133621 : PopupMenu::~PopupMenu()
    3474             : {
    3475       45047 :     if( pRefAutoSubMenu && *pRefAutoSubMenu == this )
    3476           0 :         *pRefAutoSubMenu = NULL;    // #111060# avoid second delete in ~MenuItemData
    3477       88574 : }
    3478             : 
    3479           0 : bool PopupMenu::IsInExecute()
    3480             : {
    3481           0 :     return GetActivePopupMenu() ? true : false;
    3482             : }
    3483             : 
    3484           0 : PopupMenu* PopupMenu::GetActivePopupMenu()
    3485             : {
    3486           0 :     ImplSVData* pSVData = ImplGetSVData();
    3487           0 :     return pSVData->maAppData.mpActivePopupMenu;
    3488             : }
    3489             : 
    3490           0 : void PopupMenu::EndExecute( sal_uInt16 nSelectId )
    3491             : {
    3492           0 :     if ( ImplGetWindow() )
    3493           0 :         ImplGetFloatingWindow()->EndExecute( nSelectId );
    3494           0 : }
    3495             : 
    3496           0 : void PopupMenu::SelectEntry( sal_uInt16 nId )
    3497             : {
    3498           0 :     if ( ImplGetWindow() )
    3499             :     {
    3500           0 :         if( nId != ITEMPOS_INVALID )
    3501             :         {
    3502           0 :             size_t nPos = 0;
    3503           0 :             MenuItemData* pData = GetItemList()->GetData( nId, nPos );
    3504           0 :             if (pData && pData->pSubMenu)
    3505           0 :                 ImplGetFloatingWindow()->ChangeHighlightItem( nPos, true );
    3506             :             else
    3507           0 :                 ImplGetFloatingWindow()->EndExecute( nId );
    3508             :         }
    3509             :         else
    3510             :         {
    3511           0 :             MenuFloatingWindow* pFloat = ImplGetFloatingWindow();
    3512           0 :             pFloat->GrabFocus();
    3513             : 
    3514           0 :             for( size_t nPos = 0; nPos < GetItemList()->size(); nPos++ )
    3515             :             {
    3516           0 :                 MenuItemData* pData = GetItemList()->GetDataFromPos( nPos );
    3517           0 :                 if( pData->pSubMenu )
    3518             :                 {
    3519           0 :                     pFloat->KillActivePopup();
    3520             :                 }
    3521             :             }
    3522           0 :             pFloat->ChangeHighlightItem( ITEMPOS_INVALID, false );
    3523             :         }
    3524             :     }
    3525           0 : }
    3526             : 
    3527           0 : void PopupMenu::SetSelectedEntry( sal_uInt16 nId )
    3528             : {
    3529           0 :     nSelectedId = nId;
    3530           0 : }
    3531             : 
    3532           0 : sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Point& rPopupPos )
    3533             : {
    3534           0 :     return Execute( pExecWindow, Rectangle( rPopupPos, rPopupPos ), POPUPMENU_EXECUTE_DOWN );
    3535             : }
    3536             : 
    3537           0 : sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Rectangle& rRect, sal_uInt16 nFlags )
    3538             : {
    3539           0 :     ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL window!", 0 );
    3540             : 
    3541           0 :     sal_uLong nPopupModeFlags = 0;
    3542           0 :     if ( nFlags & POPUPMENU_EXECUTE_DOWN )
    3543           0 :         nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
    3544           0 :     else if ( nFlags & POPUPMENU_EXECUTE_UP )
    3545           0 :         nPopupModeFlags = FLOATWIN_POPUPMODE_UP;
    3546           0 :     else if ( nFlags & POPUPMENU_EXECUTE_LEFT )
    3547           0 :         nPopupModeFlags = FLOATWIN_POPUPMODE_LEFT;
    3548           0 :     else if ( nFlags & POPUPMENU_EXECUTE_RIGHT )
    3549           0 :         nPopupModeFlags = FLOATWIN_POPUPMODE_RIGHT;
    3550             :     else
    3551           0 :         nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
    3552             : 
    3553           0 :     if (nFlags & POPUPMENU_NOMOUSEUPCLOSE )                      // allow popup menus to stay open on mouse button up
    3554           0 :         nPopupModeFlags |= FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;    // useful if the menu was opened on mousebutton down (eg toolbox configuration)
    3555             : 
    3556           0 :     if (nFlags & POPUPMENU_NOHORZ_PLACEMENT)
    3557           0 :         nPopupModeFlags |= FLOATWIN_POPUPMODE_NOHORZPLACEMENT;
    3558             : 
    3559           0 :     return ImplExecute( pExecWindow, rRect, nPopupModeFlags, 0, false );
    3560             : }
    3561             : 
    3562           8 : sal_uInt16 PopupMenu::ImplExecute( Window* pW, const Rectangle& rRect, sal_uLong nPopupModeFlags, Menu* pSFrom, bool bPreSelectFirst )
    3563             : {
    3564           8 :     if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
    3565           0 :         return 0;
    3566             : 
    3567           8 :     delete mpLayoutData, mpLayoutData = NULL;
    3568             : 
    3569           8 :     ImplSVData* pSVData = ImplGetSVData();
    3570             : 
    3571           8 :     pStartedFrom = pSFrom;
    3572           8 :     nSelectedId = 0;
    3573           8 :     bCanceled = false;
    3574             : 
    3575           8 :     sal_uLong nFocusId = 0;
    3576           8 :     bool bRealExecute = false;
    3577           8 :     if ( !pStartedFrom )
    3578             :     {
    3579           0 :         pSVData->maWinData.mbNoDeactivate = true;
    3580           0 :         nFocusId = Window::SaveFocus();
    3581           0 :         bRealExecute = true;
    3582             :     }
    3583             :     else
    3584             :     {
    3585             :         // assure that only one menu is open at a time
    3586           8 :         if( pStartedFrom->bIsMenuBar && pSVData->maWinData.mpFirstFloat )
    3587           0 :             pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
    3588             :     }
    3589             : 
    3590             :     DBG_ASSERT( !ImplGetWindow(), "Win?!" );
    3591           8 :     Rectangle aRect( rRect );
    3592           8 :     aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
    3593             : 
    3594           8 :     WinBits nStyle = WB_BORDER;
    3595           8 :     if ( bRealExecute )
    3596           0 :         nPopupModeFlags |= FLOATWIN_POPUPMODE_NEWLEVEL;
    3597           8 :     if ( !pStartedFrom || !pStartedFrom->bIsMenuBar )
    3598           0 :         nPopupModeFlags |= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK | FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE;
    3599             : 
    3600           8 :     nPopupModeFlags |= FLOATWIN_POPUPMODE_NOKEYCLOSE;
    3601             : 
    3602             :     // could be useful during debugging.
    3603             :     // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
    3604             : 
    3605           8 :     ImplDelData aDelData;
    3606           8 :     pW->ImplAddDel( &aDelData );
    3607             : 
    3608           8 :     bInCallback = true; // set it here, if Activate overloaded
    3609           8 :     Activate();
    3610           8 :     bInCallback = false;
    3611             : 
    3612           8 :     if ( aDelData.IsDead() )
    3613           0 :         return 0;   // Error
    3614             : 
    3615           8 :     pW->ImplRemoveDel( &aDelData );
    3616             : 
    3617           8 :     if ( bCanceled || bKilled )
    3618           0 :         return 0;
    3619             : 
    3620           8 :     if ( !GetItemCount() )
    3621           0 :         return 0;
    3622             : 
    3623             :     // The flag MENU_FLAG_HIDEDISABLEDENTRIES is inherited.
    3624           8 :     if ( pSFrom )
    3625             :     {
    3626           8 :         if ( pSFrom->nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES )
    3627           0 :             nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
    3628             :         else
    3629           8 :             nMenuFlags &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
    3630             :     }
    3631             :     else
    3632             :         // #102790# context menus shall never show disabled entries
    3633           0 :         nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
    3634             : 
    3635           8 :     sal_uInt16 nVisibleEntries = ImplGetVisibleItemCount();
    3636           8 :     if ( !nVisibleEntries )
    3637             :     {
    3638           0 :         ResMgr* pResMgr = ImplGetResMgr();
    3639           0 :         if( pResMgr )
    3640             :         {
    3641           0 :             OUString aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, *pResMgr ) );
    3642             :             MenuItemData* pData = pItemList->Insert(
    3643           0 :                 0xFFFF, MENUITEM_STRING, 0, aTmpEntryText, Image(), NULL, 0xFFFF, OString() );
    3644           0 :             size_t nPos = 0;
    3645           0 :             pData = pItemList->GetData( pData->nId, nPos );
    3646             :             assert(pData);
    3647           0 :             pData->bIsTemporary = true;
    3648           0 :             ImplCallEventListeners(VCLEVENT_MENU_SUBMENUCHANGED, nPos);
    3649             :         }
    3650             :     }
    3651           8 :     else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags & MENU_FLAG_NOAUTOMNEMONICS ) )
    3652             :     {
    3653           8 :         CreateAutoMnemonics();
    3654             :     }
    3655             : 
    3656           8 :     MenuFloatingWindow* pWin = new MenuFloatingWindow( this, pW, nStyle | WB_SYSTEMWINDOW );
    3657           8 :     if( pSVData->maNWFData.mbFlatMenu )
    3658           0 :         pWin->SetBorderStyle( WINDOW_BORDER_NOBORDER );
    3659             :     else
    3660           8 :         pWin->SetBorderStyle( pWin->GetBorderStyle() | WINDOW_BORDER_MENU );
    3661           8 :     pWindow = pWin;
    3662             : 
    3663           8 :     Size aSz = ImplCalcSize( pWin );
    3664             : 
    3665           8 :     Rectangle aDesktopRect(pWin->GetDesktopRectPixel());
    3666           8 :     if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
    3667             :     {
    3668           0 :         Window* pDeskW = pWindow->GetWindow( WINDOW_REALPARENT );
    3669           0 :         if( ! pDeskW )
    3670           0 :             pDeskW = pWindow;
    3671           0 :         Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) );
    3672             :         aDesktopRect = Application::GetScreenPosSizePixel(
    3673           0 :             Application::GetBestScreen( Rectangle( aDesktopTL, aRect.GetSize() ) ));
    3674             :     }
    3675             : 
    3676           8 :     long nMaxHeight = aDesktopRect.GetHeight();
    3677             : 
    3678             :     //rhbz#1021915. If a menu won't fit in the desired location the default
    3679             :     //mode is to place it somewhere it will fit.  e.g. above, left, right. For
    3680             :     //some cases, e.g. menubars, it's desirable to limit the options to
    3681             :     //above/below and force the menu to scroll if it won't fit
    3682           8 :     if (nPopupModeFlags & FLOATWIN_POPUPMODE_NOHORZPLACEMENT)
    3683             :     {
    3684           8 :         Window* pRef = pWin;
    3685           8 :         if ( pRef->GetParent() )
    3686           8 :             pRef = pRef->GetParent();
    3687             : 
    3688          16 :         Rectangle devRect(  pRef->OutputToAbsoluteScreenPixel( aRect.TopLeft() ),
    3689          24 :                             pRef->OutputToAbsoluteScreenPixel( aRect.BottomRight() ) );
    3690             : 
    3691           8 :         long nHeightAbove = devRect.Top() - aDesktopRect.Top();
    3692           8 :         long nHeightBelow = aDesktopRect.Bottom() - devRect.Bottom();
    3693           8 :         nMaxHeight = std::min(nMaxHeight, std::max(nHeightAbove, nHeightBelow));
    3694             :     }
    3695             : 
    3696           8 :     if ( pStartedFrom && pStartedFrom->bIsMenuBar )
    3697           8 :         nMaxHeight -= pW->GetSizePixel().Height();
    3698             :     sal_Int32 nLeft, nTop, nRight, nBottom;
    3699           8 :     pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
    3700           8 :     nMaxHeight -= nTop+nBottom;
    3701           8 :     if ( aSz.Height() > nMaxHeight )
    3702             :     {
    3703           0 :         pWin->EnableScrollMenu( true );
    3704           0 :         sal_uInt16 nStart = ImplGetFirstVisible();
    3705           0 :         sal_uInt16 nEntries = ImplCalcVisEntries( nMaxHeight, nStart );
    3706           0 :         aSz.Height() = ImplCalcHeight( nEntries );
    3707             :     }
    3708             : 
    3709           8 :     pWin->SetFocusId( nFocusId );
    3710           8 :     pWin->SetOutputSizePixel( aSz );
    3711             :     // #102158# menus must never grab the focus, otherwise
    3712             :     // they will be closed immediately
    3713             :     // from now on focus grabbing is only prohibited automatically if
    3714             :     // FLOATWIN_POPUPMODE_GRABFOCUS was set (which is done below), because some
    3715             :     // floaters (like floating toolboxes) may grab the focus
    3716             :     // pWin->GrabFocus();
    3717           8 :     if ( GetItemCount() )
    3718             :     {
    3719           8 :         SalMenu* pMenu = ImplGetSalMenu();
    3720           8 :         if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS ) )
    3721             :         {
    3722           0 :             pWin->StopExecute(0);
    3723           0 :             pWin->doShutdown();
    3724           0 :             pWindow->doLazyDelete();
    3725           0 :             pWindow = NULL;
    3726           0 :             return nSelectedId;
    3727             :         }
    3728             :         else
    3729             :         {
    3730           8 :             pWin->StartPopupMode( aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS );
    3731             :         }
    3732           8 :         if( pSFrom )
    3733             :         {
    3734             :             sal_uInt16 aPos;
    3735           8 :             if( pSFrom->bIsMenuBar )
    3736           8 :                 aPos = ((MenuBarWindow *) pSFrom->pWindow)->GetHighlightedItem();
    3737             :             else
    3738           0 :                 aPos = ((MenuFloatingWindow *) pSFrom->pWindow)->GetHighlightedItem();
    3739             : 
    3740           8 :             pWin->SetPosInParent( aPos );  // store position to be sent in SUBMENUDEACTIVATE
    3741           8 :             pSFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE, aPos );
    3742             :         }
    3743             :     }
    3744           8 :     if ( bPreSelectFirst )
    3745             :     {
    3746           0 :         size_t nCount = pItemList->size();
    3747           0 :         for ( size_t n = 0; n < nCount; n++ )
    3748             :         {
    3749           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3750           0 :             if (  (  pData->bEnabled
    3751           0 :                   || !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus()
    3752             :                   )
    3753           0 :                && ( pData->eType != MENUITEM_SEPARATOR )
    3754           0 :                && ImplIsVisible( n )
    3755           0 :                && ImplIsSelectable( n )
    3756             :                )
    3757             :             {
    3758           0 :                 pWin->ChangeHighlightItem( n, false );
    3759           0 :                 break;
    3760             :             }
    3761             :         }
    3762             :     }
    3763           8 :     if ( bRealExecute )
    3764             :     {
    3765           0 :         pWin->ImplAddDel( &aDelData );
    3766             : 
    3767           0 :         ImplDelData aModalWinDel;
    3768           0 :         pW->ImplAddDel( &aModalWinDel );
    3769           0 :         pW->ImplIncModalCount();
    3770             : 
    3771           0 :         pWin->Execute();
    3772             : 
    3773             :         DBG_ASSERT( ! aModalWinDel.IsDead(), "window for popup died, modal count incorrect !" );
    3774           0 :         if( ! aModalWinDel.IsDead() )
    3775           0 :             pW->ImplDecModalCount();
    3776             : 
    3777           0 :         if ( !aDelData.IsDead() )
    3778           0 :             pWin->ImplRemoveDel( &aDelData );
    3779             :         else
    3780           0 :             return 0;
    3781             : 
    3782             :         // Restore focus (could already have been
    3783             :         // restored in Select)
    3784           0 :         nFocusId = pWin->GetFocusId();
    3785           0 :         if ( nFocusId )
    3786             :         {
    3787           0 :             pWin->SetFocusId( 0 );
    3788           0 :             pSVData->maWinData.mbNoDeactivate = false;
    3789             :         }
    3790           0 :         pWin->ImplEndPopupMode( 0, nFocusId );
    3791             : 
    3792           0 :         if ( nSelectedId )  // then clean up .. ( otherwise done by TH )
    3793             :         {
    3794           0 :             PopupMenu* pSub = pWin->GetActivePopup();
    3795           0 :             while ( pSub )
    3796             :             {
    3797           0 :                 pSub->ImplGetFloatingWindow()->EndPopupMode();
    3798           0 :                 pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
    3799             :             }
    3800             :         }
    3801           0 :         pWin->doShutdown();
    3802           0 :         pWindow->doLazyDelete();
    3803           0 :         pWindow = NULL;
    3804             : 
    3805             :         // is there still Select?
    3806           0 :         Menu* pSelect = ImplFindSelectMenu();
    3807           0 :         if ( pSelect )
    3808             :         {
    3809             :             // Select should be called prior to leaving execute in a popup menu!
    3810           0 :             Application::RemoveUserEvent( pSelect->nEventId );
    3811           0 :             pSelect->nEventId = 0;
    3812           0 :             pSelect->Select();
    3813           0 :         }
    3814             :     }
    3815             : 
    3816           8 :     return bRealExecute ? nSelectedId : 0;
    3817             : }
    3818             : 
    3819           0 : sal_uInt16 PopupMenu::ImplCalcVisEntries( long nMaxHeight, sal_uInt16 nStartEntry, sal_uInt16* pLastVisible ) const
    3820             : {
    3821           0 :     nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
    3822             : 
    3823           0 :     long nHeight = 0;
    3824           0 :     size_t nEntries = pItemList->size();
    3825           0 :     sal_uInt16 nVisEntries = 0;
    3826             : 
    3827           0 :     if ( pLastVisible )
    3828           0 :         *pLastVisible = 0;
    3829             : 
    3830           0 :     for ( size_t n = nStartEntry; n < nEntries; n++ )
    3831             :     {
    3832           0 :         if ( ImplIsVisible( n ) )
    3833             :         {
    3834           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3835           0 :             nHeight += pData->aSz.Height();
    3836           0 :             if ( nHeight > nMaxHeight )
    3837           0 :                 break;
    3838             : 
    3839           0 :             if ( pLastVisible )
    3840           0 :                 *pLastVisible = n;
    3841           0 :             nVisEntries++;
    3842             :         }
    3843             :     }
    3844           0 :     return nVisEntries;
    3845             : }
    3846             : 
    3847           0 : long PopupMenu::ImplCalcHeight( sal_uInt16 nEntries ) const
    3848             : {
    3849           0 :     long nHeight = 0;
    3850             : 
    3851           0 :     sal_uInt16 nFound = 0;
    3852           0 :     for ( size_t n = 0; ( nFound < nEntries ) && ( n < pItemList->size() ); n++ )
    3853             :     {
    3854           0 :         if ( ImplIsVisible( (sal_uInt16) n ) )
    3855             :         {
    3856           0 :             MenuItemData* pData = pItemList->GetDataFromPos( n );
    3857           0 :             nHeight += pData->aSz.Height();
    3858           0 :             nFound++;
    3859             :         }
    3860             :     }
    3861             : 
    3862           0 :     nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
    3863             : 
    3864           0 :     return nHeight;
    3865             : }
    3866             : 
    3867        2051 : static void ImplInitMenuWindow( Window* pWin, bool bFont, bool bMenuBar )
    3868             : {
    3869        2051 :     const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
    3870             : 
    3871        2051 :     if ( bFont )
    3872        2051 :         pWin->SetPointFont( rStyleSettings.GetMenuFont() );
    3873        2051 :     if( bMenuBar )
    3874             :     {
    3875        2043 :         const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader();
    3876        2043 :         if ( !rPersonaBitmap.IsEmpty() )
    3877             :         {
    3878           0 :             Wallpaper aWallpaper( rPersonaBitmap );
    3879           0 :             aWallpaper.SetStyle( WALLPAPER_TOPRIGHT );
    3880           0 :             aWallpaper.SetColor( Application::GetSettings().GetStyleSettings().GetWorkspaceColor() );
    3881             : 
    3882           0 :             pWin->SetBackground( aWallpaper );
    3883           0 :             pWin->SetPaintTransparent( false );
    3884           0 :             pWin->SetParentClipMode( 0 );
    3885             :         }
    3886        2043 :         else if ( pWin->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
    3887             :         {
    3888           0 :             pWin->SetBackground();  // background will be drawn by NWF
    3889             :         }
    3890             :         else
    3891             :         {
    3892        2043 :             Wallpaper aWallpaper;
    3893        2043 :             aWallpaper.SetStyle( WALLPAPER_APPLICATIONGRADIENT );
    3894        2043 :             pWin->SetBackground( aWallpaper );
    3895        2043 :             pWin->SetPaintTransparent( false );
    3896        2043 :             pWin->SetParentClipMode( 0 );
    3897        2043 :         }
    3898             :     }
    3899             :     else
    3900             :     {
    3901           8 :         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
    3902             :         {
    3903           0 :             pWin->SetBackground();  // background will be drawn by NWF
    3904             :         }
    3905             :         else
    3906           8 :             pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
    3907             :     }
    3908             : 
    3909        2051 :     if ( bMenuBar )
    3910        2043 :         pWin->SetTextColor( rStyleSettings.GetMenuBarTextColor() );
    3911             :     else
    3912           8 :         pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
    3913        2051 :     pWin->SetTextFillColor();
    3914        2051 :     pWin->SetLineColor();
    3915        2051 : }
    3916             : 
    3917           8 : MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, Window* pParent, WinBits nStyle ) :
    3918           8 :     FloatingWindow( pParent, nStyle )
    3919             : {
    3920           8 :     mpWindowImpl->mbMenuFloatingWindow= true;
    3921           8 :     pMenu               = pMen;
    3922           8 :     pActivePopup        = 0;
    3923           8 :     nSaveFocusId        = 0;
    3924           8 :     bInExecute          = false;
    3925           8 :     bScrollMenu         = false;
    3926           8 :     nHighlightedItem    = ITEMPOS_INVALID;
    3927           8 :     nMBDownPos          = ITEMPOS_INVALID;
    3928           8 :     nPosInParent        = ITEMPOS_INVALID;
    3929           8 :     nScrollerHeight     = 0;
    3930           8 :     nBorder             = EXTRASPACEY;
    3931           8 :     nFirstEntry         = 0;
    3932           8 :     bScrollUp           = false;
    3933           8 :     bScrollDown         = false;
    3934           8 :     bIgnoreFirstMove    = true;
    3935           8 :     bKeyInput           = false;
    3936             : 
    3937           8 :     EnableSaveBackground();
    3938           8 :     ImplInitMenuWindow( this, true, false );
    3939             : 
    3940           8 :     SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
    3941             : 
    3942           8 :     aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
    3943           8 :     aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
    3944           8 :     aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
    3945           8 :     aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
    3946           8 :     aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
    3947             : 
    3948           8 :     AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
    3949           8 : }
    3950             : 
    3951          16 : void MenuFloatingWindow::doShutdown()
    3952             : {
    3953          16 :     if( pMenu )
    3954             :     {
    3955             :         // #105373# notify toolkit that highlight was removed
    3956             :         // otherwise the entry will not be read when the menu is opened again
    3957           8 :         if( nHighlightedItem != ITEMPOS_INVALID )
    3958           0 :             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
    3959           8 :         pMenu->SetHighlightItem(ITEMPOS_INVALID);
    3960           8 :         if( !bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
    3961             :         {
    3962             :             // #102461# remove highlight in parent
    3963             :             MenuItemData* pData;
    3964           0 :             size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
    3965           0 :             for(i = 0; i < nCount; i++)
    3966             :             {
    3967           0 :                 pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
    3968           0 :                 if( pData && ( pData->pSubMenu == pMenu ) )
    3969           0 :                     break;
    3970             :             }
    3971           0 :             if( i < nCount )
    3972             :             {
    3973           0 :                 MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
    3974           0 :                 if( pPWin )
    3975           0 :                     pPWin->HighlightItem( i, false );
    3976             :             }
    3977             :         }
    3978             : 
    3979             :         // free the reference to the accessible component
    3980           8 :         SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
    3981             : 
    3982           8 :         aHighlightChangedTimer.Stop();
    3983             : 
    3984             :         // #95056# invalidate screen area covered by system window
    3985             :         // so this can be taken into account if the commandhandler performs a scroll operation
    3986           8 :         if( GetParent() )
    3987             :         {
    3988           8 :             Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
    3989           8 :             GetParent()->Invalidate( aInvRect );
    3990             :         }
    3991           8 :         pMenu = NULL;
    3992           8 :         RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
    3993             :     }
    3994          16 : }
    3995             : 
    3996          24 : MenuFloatingWindow::~MenuFloatingWindow()
    3997             : {
    3998           8 :     doShutdown();
    3999          16 : }
    4000             : 
    4001           8 : void MenuFloatingWindow::Resize()
    4002             : {
    4003           8 :     ImplInitClipRegion();
    4004           8 : }
    4005             : 
    4006           8 : long MenuFloatingWindow::ImplGetStartY() const
    4007             : {
    4008           8 :     long nY = 0;
    4009           8 :     if( pMenu )
    4010             :     {
    4011           8 :         for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
    4012           0 :             nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
    4013             :     }
    4014           8 :     return -nY;
    4015             : }
    4016             : 
    4017           0 : Region MenuFloatingWindow::ImplCalcClipRegion( bool bIncludeLogo ) const
    4018             : {
    4019           0 :     Size aOutSz = GetOutputSizePixel();
    4020           0 :     Point aPos;
    4021           0 :     Rectangle aRect( aPos, aOutSz );
    4022           0 :     aRect.Top() += nScrollerHeight;
    4023           0 :     aRect.Bottom() -= nScrollerHeight;
    4024             : 
    4025           0 :     if ( pMenu && pMenu->pLogo && !bIncludeLogo )
    4026           0 :         aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
    4027             : 
    4028           0 :     Region aRegion(aRect);
    4029           0 :     if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
    4030           0 :         aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
    4031             : 
    4032           0 :     return aRegion;
    4033             : }
    4034             : 
    4035           8 : void MenuFloatingWindow::ImplInitClipRegion()
    4036             : {
    4037           8 :     if ( IsScrollMenu() )
    4038             :     {
    4039           0 :         SetClipRegion( ImplCalcClipRegion() );
    4040             :     }
    4041             :     else
    4042             :     {
    4043           8 :         SetClipRegion();
    4044             :     }
    4045           8 : }
    4046             : 
    4047           0 : void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, bool bMBDown )
    4048             : {
    4049           0 :     if( ! pMenu )
    4050           0 :         return;
    4051             : 
    4052           0 :     long nY = nScrollerHeight + ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    4053           0 :     long nMouseY = rMEvt.GetPosPixel().Y();
    4054           0 :     Size aOutSz = GetOutputSizePixel();
    4055           0 :     if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() - nY ) ) )
    4056             :     {
    4057           0 :         bool bHighlighted = false;
    4058           0 :         size_t nCount = pMenu->pItemList->size();
    4059           0 :         nY += ImplGetStartY();  // ggf. gescrollt.
    4060           0 :         for ( size_t n = 0; !bHighlighted && ( n < nCount ); n++ )
    4061             :         {
    4062           0 :             if ( pMenu->ImplIsVisible( n ) )
    4063             :             {
    4064           0 :                 MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
    4065           0 :                 long nOldY = nY;
    4066           0 :                 nY += pItemData->aSz.Height();
    4067           0 :                 if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
    4068             :                 {
    4069           0 :                     bool bPopupArea = true;
    4070           0 :                     if ( pItemData->nBits & MIB_POPUPSELECT )
    4071             :                     {
    4072             :                         // only when clicked over the arrow...
    4073           0 :                         Size aSz = GetOutputSizePixel();
    4074           0 :                         long nFontHeight = GetTextHeight();
    4075           0 :                         bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
    4076             :                     }
    4077             : 
    4078           0 :                     if ( bMBDown )
    4079             :                     {
    4080           0 :                         if ( n != nHighlightedItem )
    4081             :                         {
    4082           0 :                             ChangeHighlightItem( (sal_uInt16)n, false );
    4083             :                         }
    4084             : 
    4085           0 :                         bool bAllowNewPopup = true;
    4086           0 :                         if ( pActivePopup )
    4087             :                         {
    4088           0 :                             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    4089           0 :                             bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
    4090           0 :                             if ( bAllowNewPopup )
    4091           0 :                                 KillActivePopup();
    4092             :                         }
    4093             : 
    4094           0 :                         if ( bPopupArea && bAllowNewPopup )
    4095             :                         {
    4096           0 :                             HighlightChanged( NULL );
    4097             :                         }
    4098             :                     }
    4099             :                     else
    4100             :                     {
    4101           0 :                         if ( n != nHighlightedItem )
    4102             :                         {
    4103           0 :                             ChangeHighlightItem( (sal_uInt16)n, true );
    4104             :                         }
    4105           0 :                         else if ( pItemData->nBits & MIB_POPUPSELECT )
    4106             :                         {
    4107           0 :                             if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
    4108           0 :                                 HighlightChanged( NULL );
    4109             :                         }
    4110             :                     }
    4111           0 :                     bHighlighted = true;
    4112             :                 }
    4113             :             }
    4114             :         }
    4115           0 :         if ( !bHighlighted )
    4116           0 :             ChangeHighlightItem( ITEMPOS_INVALID, true );
    4117             :     }
    4118             :     else
    4119             :     {
    4120           0 :         ImplScroll( rMEvt.GetPosPixel() );
    4121           0 :         ChangeHighlightItem( ITEMPOS_INVALID, true );
    4122             :     }
    4123             : }
    4124             : 
    4125           0 : IMPL_LINK_NOARG(MenuFloatingWindow, PopupEnd)
    4126             : {
    4127             :     // "this" will be deleted before the end of this method!
    4128           0 :     Menu* pM = pMenu;
    4129           0 :     if ( bInExecute )
    4130             :     {
    4131           0 :         if ( pActivePopup )
    4132             :         {
    4133             :             //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
    4134           0 :             KillActivePopup(); // should be ok to just remove it
    4135             :             //pActivePopup->bCanceled = true;
    4136             :         }
    4137           0 :         bInExecute = false;
    4138           0 :         pMenu->bInCallback = true;
    4139           0 :         pMenu->Deactivate();
    4140           0 :         pMenu->bInCallback = false;
    4141             :     }
    4142             :     else
    4143             :     {
    4144           0 :         if( pMenu )
    4145             :         {
    4146             :             // if the window was closed by TH, there is another menu
    4147             :             // which has this window as pActivePopup
    4148           0 :             if ( pMenu->pStartedFrom )
    4149             :             {
    4150             :                 // pWin from parent could be 0, if the list is
    4151             :                 // cleaned from the start, now clean up the endpopup-events
    4152           0 :                 if ( pMenu->pStartedFrom->bIsMenuBar )
    4153             :                 {
    4154           0 :                     MenuBarWindow* p = (MenuBarWindow*) pMenu->pStartedFrom->ImplGetWindow();
    4155           0 :                     if ( p )
    4156           0 :                         p->PopupClosed( pMenu );
    4157             :                 }
    4158             :                 else
    4159             :                 {
    4160           0 :                     MenuFloatingWindow* p = (MenuFloatingWindow*) pMenu->pStartedFrom->ImplGetWindow();
    4161           0 :                     if ( p )
    4162           0 :                         p->KillActivePopup( (PopupMenu*)pMenu );
    4163             :                 }
    4164             :             }
    4165             :         }
    4166             :     }
    4167             : 
    4168           0 :     if ( pM )
    4169           0 :         pM->pStartedFrom = 0;
    4170             : 
    4171           0 :     return 0;
    4172             : }
    4173             : 
    4174           0 : IMPL_LINK_NOARG(MenuFloatingWindow, AutoScroll)
    4175             : {
    4176           0 :     ImplScroll( GetPointerPosPixel() );
    4177           0 :     return 1;
    4178             : }
    4179             : 
    4180           0 : IMPL_LINK( MenuFloatingWindow, HighlightChanged, Timer*, pTimer )
    4181             : {
    4182           0 :     if( ! pMenu )
    4183           0 :         return 0;
    4184             : 
    4185           0 :     MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
    4186           0 :     if ( pItemData )
    4187             :     {
    4188           0 :         if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
    4189             :         {
    4190           0 :             sal_uLong nOldFlags = GetPopupModeFlags();
    4191           0 :             SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
    4192           0 :             KillActivePopup();
    4193           0 :             SetPopupModeFlags( nOldFlags );
    4194             :         }
    4195           0 :         if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
    4196             :         {
    4197           0 :             pActivePopup = (PopupMenu*)pItemData->pSubMenu;
    4198           0 :             long nY = nScrollerHeight+ImplGetStartY();
    4199           0 :             MenuItemData* pData = 0;
    4200           0 :             for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
    4201             :             {
    4202           0 :                 pData = pMenu->pItemList->GetDataFromPos( n );
    4203           0 :                 nY += pData->aSz.Height();
    4204             :             }
    4205           0 :             pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
    4206           0 :             Size MySize = GetOutputSizePixel();
    4207           0 :             Point aItemTopLeft( 0, nY );
    4208           0 :             Point aItemBottomRight( aItemTopLeft );
    4209           0 :             aItemBottomRight.X() += MySize.Width();
    4210           0 :             aItemBottomRight.Y() += pData->aSz.Height();
    4211             : 
    4212             :             // shift the popups a little
    4213           0 :             aItemTopLeft.X() += 2;
    4214           0 :             aItemBottomRight.X() -= 2;
    4215           0 :             if ( nHighlightedItem )
    4216           0 :                 aItemTopLeft.Y() -= 2;
    4217             :             else
    4218             :             {
    4219             :                 sal_Int32 nL, nT, nR, nB;
    4220           0 :                 GetBorder( nL, nT, nR, nB );
    4221           0 :                 aItemTopLeft.Y() -= nT;
    4222             :             }
    4223             : 
    4224             :             // pTest: crash due to Reschedule() in call of Activate()
    4225             :             // Also it is prevented that submenus are displayed which
    4226             :             // were for long in Activate Rescheduled and which should not be
    4227             :             // displayed now.
    4228           0 :             Menu* pTest = pActivePopup;
    4229           0 :             sal_uLong nOldFlags = GetPopupModeFlags();
    4230           0 :             SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
    4231           0 :             sal_uInt16 nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_RIGHT, pMenu, pTimer ? false : true  );
    4232           0 :             SetPopupModeFlags( nOldFlags );
    4233             : 
    4234             :             // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
    4235           0 :             if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
    4236           0 :                 pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
    4237             :         }
    4238             :     }
    4239             : 
    4240           0 :     return 0;
    4241             : }
    4242             : 
    4243           0 : IMPL_LINK_NOARG(MenuFloatingWindow, SubmenuClose)
    4244             : {
    4245           0 :     if( pMenu && pMenu->pStartedFrom )
    4246             :     {
    4247           0 :         MenuFloatingWindow* pWin = (MenuFloatingWindow*) pMenu->pStartedFrom->GetWindow();
    4248           0 :         if( pWin )
    4249           0 :             pWin->KillActivePopup();
    4250             :     }
    4251           0 :     return 0;
    4252             : }
    4253             : 
    4254          96 : IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
    4255             : {
    4256          48 :     if( ! pMenu )
    4257           0 :         return 0;
    4258             : 
    4259          48 :     if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
    4260          16 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
    4261          32 :     else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
    4262          16 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
    4263          48 :     return 0;
    4264             : }
    4265             : 
    4266           0 : void MenuFloatingWindow::EnableScrollMenu( bool b )
    4267             : {
    4268           0 :     bScrollMenu = b;
    4269           0 :     nScrollerHeight = b ? (sal_uInt16) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
    4270           0 :     bScrollDown = true;
    4271           0 :     ImplInitClipRegion();
    4272           0 : }
    4273             : 
    4274           0 : void MenuFloatingWindow::Execute()
    4275             : {
    4276           0 :     ImplSVData* pSVData = ImplGetSVData();
    4277             : 
    4278           0 :     pSVData->maAppData.mpActivePopupMenu = (PopupMenu*)pMenu;
    4279             : 
    4280           0 :     bInExecute = true;
    4281             : //  bCallingSelect = false;
    4282             : 
    4283           0 :     while ( bInExecute )
    4284           0 :         Application::Yield();
    4285             : 
    4286           0 :     pSVData->maAppData.mpActivePopupMenu = NULL;
    4287           0 : }
    4288             : 
    4289           8 : void MenuFloatingWindow::StopExecute( sal_uLong nFocusId )
    4290             : {
    4291             :     // restore focus
    4292             :     // (could have been restored in Select)
    4293           8 :     if ( nSaveFocusId )
    4294             :     {
    4295           0 :         Window::EndSaveFocus( nFocusId, false );
    4296           0 :         nFocusId = nSaveFocusId;
    4297           0 :         if ( nFocusId )
    4298             :         {
    4299           0 :             nSaveFocusId = 0;
    4300           0 :             ImplGetSVData()->maWinData.mbNoDeactivate = false;
    4301             :         }
    4302             :     }
    4303           8 :     ImplEndPopupMode( 0, nFocusId );
    4304             : 
    4305           8 :     aHighlightChangedTimer.Stop();
    4306           8 :     bInExecute = false;
    4307           8 :     if ( pActivePopup )
    4308             :     {
    4309           0 :         KillActivePopup();
    4310             :     }
    4311             :     // notify parent, needed for accessibility
    4312           8 :     if( pMenu && pMenu->pStartedFrom )
    4313           8 :         pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
    4314           8 : }
    4315             : 
    4316           0 : void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
    4317             : {
    4318           0 :     if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
    4319             :     {
    4320           0 :         if( pActivePopup->pWindow != NULL )
    4321           0 :             if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
    4322           0 :                 return; // kill it later
    4323           0 :         if ( pActivePopup->bInCallback )
    4324           0 :             pActivePopup->bCanceled = true;
    4325             : 
    4326             :         // For all actions pActivePopup = 0, if e.g.
    4327             :         // PopupModeEndHdl the popups to destroy were called synchronous
    4328           0 :         PopupMenu* pPopup = pActivePopup;
    4329           0 :         pActivePopup = NULL;
    4330           0 :         pPopup->bInCallback = true;
    4331           0 :         pPopup->Deactivate();
    4332           0 :         pPopup->bInCallback = false;
    4333           0 :         if ( pPopup->ImplGetWindow() )
    4334             :         {
    4335           0 :             pPopup->ImplGetFloatingWindow()->StopExecute();
    4336           0 :             pPopup->ImplGetFloatingWindow()->doShutdown();
    4337           0 :             pPopup->pWindow->doLazyDelete();
    4338           0 :             pPopup->pWindow = NULL;
    4339             : 
    4340           0 :             Update();
    4341             :         }
    4342             :     }
    4343             : }
    4344             : 
    4345           0 : void MenuFloatingWindow::EndExecute()
    4346             : {
    4347           0 :     Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
    4348           0 :     sal_uLong nFocusId = 0;
    4349           0 :     if ( pStart && pStart->bIsMenuBar )
    4350             :     {
    4351           0 :         nFocusId = ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->GetFocusId();
    4352           0 :         if ( nFocusId )
    4353             :         {
    4354           0 :             ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->SetFocusId( 0 );
    4355           0 :             ImplGetSVData()->maWinData.mbNoDeactivate = false;
    4356             :         }
    4357             :     }
    4358             : 
    4359             :     // if started else where, cleanup there as well
    4360           0 :     MenuFloatingWindow* pCleanUpFrom = this;
    4361           0 :     MenuFloatingWindow* pWin = this;
    4362           0 :     while ( pWin && !pWin->bInExecute &&
    4363           0 :         pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->bIsMenuBar )
    4364             :     {
    4365           0 :         pWin = ((PopupMenu*)pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
    4366             :     }
    4367           0 :     if ( pWin )
    4368           0 :         pCleanUpFrom = pWin;
    4369             : 
    4370             :     // this window will be destroyed => store date locally...
    4371           0 :     Menu* pM = pMenu;
    4372           0 :     sal_uInt16 nItem = nHighlightedItem;
    4373             : 
    4374           0 :     pCleanUpFrom->StopExecute( nFocusId );
    4375             : 
    4376           0 :     if ( nItem != ITEMPOS_INVALID && pM )
    4377             :     {
    4378           0 :         MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
    4379           0 :         if ( pItemData && !pItemData->bIsTemporary )
    4380             :         {
    4381           0 :             pM->nSelectedId = pItemData->nId;
    4382           0 :             if ( pStart )
    4383           0 :                 pStart->nSelectedId = pItemData->nId;
    4384             : 
    4385           0 :             pM->ImplSelect();
    4386             :         }
    4387             :     }
    4388           0 : }
    4389             : 
    4390           0 : void MenuFloatingWindow::EndExecute( sal_uInt16 nId )
    4391             : {
    4392             :     size_t nPos;
    4393           0 :     if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
    4394           0 :         nHighlightedItem = nPos;
    4395             :     else
    4396           0 :         nHighlightedItem = ITEMPOS_INVALID;
    4397             : 
    4398           0 :     EndExecute();
    4399           0 : }
    4400             : 
    4401           0 : void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
    4402             : {
    4403             :     // TH creates a ToTop on this window, but the active popup
    4404             :     // should stay on top...
    4405             :     // due to focus change this would close all menus -> don't do it (#94123)
    4406             :     //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
    4407             :     //    pActivePopup->ImplGetFloatingWindow()->ToTop( TOTOP_NOGRABFOCUS );
    4408             : 
    4409           0 :     ImplHighlightItem( rMEvt, true );
    4410             : 
    4411           0 :     nMBDownPos = nHighlightedItem;
    4412           0 : }
    4413             : 
    4414           0 : void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
    4415             : {
    4416           0 :     MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
    4417             :     // nMBDownPos store in local variable and reset immediately,
    4418             :     // as it will be too late after EndExecute
    4419           0 :     sal_uInt16 _nMBDownPos = nMBDownPos;
    4420           0 :     nMBDownPos = ITEMPOS_INVALID;
    4421           0 :     if ( pData && pData->bEnabled && ( pData->eType != MENUITEM_SEPARATOR ) )
    4422             :     {
    4423           0 :         if ( !pData->pSubMenu )
    4424             :         {
    4425           0 :             EndExecute();
    4426             :         }
    4427           0 :         else if ( ( pData->nBits & MIB_POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
    4428             :         {
    4429             :             // not when clicked over the arrow...
    4430           0 :             Size aSz = GetOutputSizePixel();
    4431           0 :             long nFontHeight = GetTextHeight();
    4432           0 :             if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
    4433           0 :                 EndExecute();
    4434             :         }
    4435             :     }
    4436             : 
    4437           0 : }
    4438             : 
    4439           0 : void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
    4440             : {
    4441           0 :     if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
    4442           0 :         return;
    4443             : 
    4444           0 :     if ( rMEvt.IsLeaveWindow() )
    4445             :     {
    4446             :         // #102461# do not remove highlight if a popup menu is open at this position
    4447           0 :         MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
    4448             :         // close popup with some delayed if we leave somewhere else
    4449           0 :         if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
    4450           0 :             pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
    4451             : 
    4452           0 :         if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
    4453           0 :             ChangeHighlightItem( ITEMPOS_INVALID, false );
    4454             : 
    4455           0 :         if ( IsScrollMenu() )
    4456           0 :             ImplScroll( rMEvt.GetPosPixel() );
    4457             :     }
    4458             :     else
    4459             :     {
    4460           0 :         aSubmenuCloseTimer.Stop();
    4461           0 :         if( bIgnoreFirstMove )
    4462           0 :             bIgnoreFirstMove = false;
    4463             :         else
    4464           0 :             ImplHighlightItem( rMEvt, false );
    4465             :     }
    4466             : }
    4467             : 
    4468           0 : void MenuFloatingWindow::ImplScroll( bool bUp )
    4469             : {
    4470           0 :     KillActivePopup();
    4471           0 :     Update();
    4472             : 
    4473           0 :     if( ! pMenu )
    4474           0 :         return;
    4475             : 
    4476           0 :     HighlightItem( nHighlightedItem, false );
    4477             : 
    4478           0 :     pMenu->ImplKillLayoutData();
    4479             : 
    4480           0 :     if ( bScrollUp && bUp )
    4481             :     {
    4482           0 :         nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
    4483             :         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
    4484             : 
    4485           0 :         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
    4486             : 
    4487           0 :         if ( !bScrollDown )
    4488             :         {
    4489           0 :             bScrollDown = true;
    4490           0 :             ImplDrawScroller( false );
    4491             :         }
    4492             : 
    4493           0 :         if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
    4494             :         {
    4495           0 :             bScrollUp = false;
    4496           0 :             ImplDrawScroller( true );
    4497             :         }
    4498             : 
    4499           0 :         Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), SCROLL_CLIP );
    4500             :     }
    4501           0 :     else if ( bScrollDown && !bUp )
    4502             :     {
    4503           0 :         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
    4504             : 
    4505           0 :         nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
    4506             :         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
    4507             : 
    4508           0 :         if ( !bScrollUp )
    4509             :         {
    4510           0 :             bScrollUp = true;
    4511           0 :             ImplDrawScroller( true );
    4512             :         }
    4513             : 
    4514           0 :         long nHeight = GetOutputSizePixel().Height();
    4515             :         sal_uInt16 nLastVisible;
    4516           0 :         ((PopupMenu*)pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
    4517           0 :         if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
    4518             :         {
    4519           0 :             bScrollDown = false;
    4520           0 :             ImplDrawScroller( false );
    4521             :         }
    4522             : 
    4523           0 :         Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), SCROLL_CLIP );
    4524             :     }
    4525             : 
    4526           0 :     HighlightItem( nHighlightedItem, true );
    4527             : }
    4528             : 
    4529           0 : void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
    4530             : {
    4531           0 :     Size aOutSz = GetOutputSizePixel();
    4532             : 
    4533           0 :     long nY = nScrollerHeight;
    4534           0 :     long nMouseY = rMousePos.Y();
    4535           0 :     long nDelta = 0;
    4536             : 
    4537           0 :     if ( bScrollUp && ( nMouseY < nY ) )
    4538             :     {
    4539           0 :         ImplScroll( true );
    4540           0 :         nDelta = nY - nMouseY;
    4541             :     }
    4542           0 :     else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
    4543             :     {
    4544           0 :         ImplScroll( false );
    4545           0 :         nDelta = nMouseY - ( aOutSz.Height() - nY );
    4546             :     }
    4547             : 
    4548           0 :     if ( nDelta )
    4549             :     {
    4550           0 :         aScrollTimer.Stop();    // if scrolled through MouseMove.
    4551             :         long nTimeout;
    4552           0 :         if ( nDelta < 3 )
    4553           0 :             nTimeout = 200;
    4554           0 :         else if ( nDelta < 5 )
    4555           0 :             nTimeout = 100;
    4556           0 :         else if ( nDelta < 8 )
    4557           0 :             nTimeout = 70;
    4558           0 :         else if ( nDelta < 12 )
    4559           0 :             nTimeout = 40;
    4560             :         else
    4561           0 :             nTimeout = 20;
    4562           0 :         aScrollTimer.SetTimeout( nTimeout );
    4563           0 :         aScrollTimer.Start();
    4564             :     }
    4565           0 : }
    4566           0 : void MenuFloatingWindow::ChangeHighlightItem( sal_uInt16 n, bool bStartPopupTimer )
    4567             : {
    4568             :     // #57934# ggf. immediately close the active, as TH's backgroundstorage works.
    4569             :     // #65750# we prefer to refrain from the background storage of small lines.
    4570             :     //         otherwise the menus are difficult to operate.
    4571             :     //  MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
    4572             :     //  if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
    4573             :     //      KillActivePopup();
    4574             : 
    4575           0 :     aSubmenuCloseTimer.Stop();
    4576           0 :     if( ! pMenu )
    4577           0 :         return;
    4578             : 
    4579           0 :     if ( nHighlightedItem != ITEMPOS_INVALID )
    4580             :     {
    4581           0 :         HighlightItem( nHighlightedItem, false );
    4582           0 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
    4583             :     }
    4584             : 
    4585           0 :     nHighlightedItem = (sal_uInt16)n;
    4586             :     DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
    4587           0 :     if( nHighlightedItem != ITEMPOS_INVALID )
    4588             :     {
    4589           0 :         if( pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
    4590             :         {
    4591             :             // #102461# make sure parent entry is highlighted as well
    4592             :             MenuItemData* pData;
    4593           0 :             size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
    4594           0 :             for(i = 0; i < nCount; i++)
    4595             :             {
    4596           0 :                 pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
    4597           0 :                 if( pData && ( pData->pSubMenu == pMenu ) )
    4598           0 :                     break;
    4599             :             }
    4600           0 :             if( i < nCount )
    4601             :             {
    4602           0 :                 MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
    4603           0 :                 if( pPWin && pPWin->nHighlightedItem != i )
    4604             :                 {
    4605           0 :                     pPWin->HighlightItem( i, true );
    4606           0 :                     pPWin->nHighlightedItem = i;
    4607             :                 }
    4608             :             }
    4609             :         }
    4610           0 :         HighlightItem( nHighlightedItem, true );
    4611           0 :         pMenu->SetHighlightItem(nHighlightedItem);
    4612           0 :         pMenu->ImplCallHighlight( nHighlightedItem );
    4613             :     }
    4614             :     else
    4615           0 :         pMenu->nSelectedId = 0;
    4616             : 
    4617           0 :     if ( bStartPopupTimer )
    4618             :     {
    4619             :         // #102438# Menu items are not selectable
    4620             :         // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
    4621             :         // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
    4622             :         // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
    4623           0 :         if ( GetSettings().GetMouseSettings().GetMenuDelay() )
    4624           0 :             aHighlightChangedTimer.Start();
    4625             :         else
    4626           0 :             HighlightChanged( &aHighlightChangedTimer );
    4627             :     }
    4628             : }
    4629             : 
    4630           0 : void MenuFloatingWindow::HighlightItem( sal_uInt16 nPos, bool bHighlight )
    4631             : {
    4632           0 :     if( ! pMenu )
    4633           0 :         return;
    4634             : 
    4635           0 :     Size    aSz = GetOutputSizePixel();
    4636           0 :     long    nStartY = ImplGetStartY();
    4637           0 :     long    nY = nScrollerHeight + nStartY + ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
    4638           0 :     long    nX = 0;
    4639             : 
    4640           0 :     if ( pMenu->pLogo )
    4641           0 :         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
    4642             : 
    4643           0 :     int nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
    4644             : 
    4645           0 :     size_t nCount = pMenu->pItemList->size();
    4646           0 :     for ( size_t n = 0; n < nCount; n++ )
    4647             :     {
    4648           0 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    4649           0 :         if ( n == nPos )
    4650             :         {
    4651             :             DBG_ASSERT( pMenu->ImplIsVisible( n ), "Highlight: Item not visible!" );
    4652           0 :             if ( pData->eType != MENUITEM_SEPARATOR )
    4653             :             {
    4654           0 :                 bool bRestoreLineColor = false;
    4655           0 :                 Color oldLineColor;
    4656           0 :                 bool bDrawItemRect = true;
    4657             : 
    4658           0 :                 Rectangle aItemRect( Point( nX+nOuterSpaceX, nY ), Size( aSz.Width()-2*nOuterSpaceX, pData->aSz.Height() ) );
    4659           0 :                 if ( pData->nBits & MIB_POPUPSELECT )
    4660             :                 {
    4661           0 :                     long nFontHeight = GetTextHeight();
    4662           0 :                     aItemRect.Right() -= nFontHeight + nFontHeight/4;
    4663             :                 }
    4664             : 
    4665           0 :                 if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
    4666             :                 {
    4667           0 :                     Size aPxSize( GetOutputSizePixel() );
    4668           0 :                     Push( PUSH_CLIPREGION );
    4669           0 :                     IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) ) );
    4670           0 :                     Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
    4671           0 :                     MenupopupValue aVal( pMenu->nTextPos-GUTTERBORDER, aItemRect );
    4672             :                     DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
    4673             :                                        aCtrlRect,
    4674             :                                        CTRL_STATE_ENABLED,
    4675             :                                        aVal,
    4676           0 :                                        OUString() );
    4677           0 :                     if( bHighlight &&
    4678           0 :                         IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
    4679             :                     {
    4680           0 :                         bDrawItemRect = false;
    4681           0 :                         if( !DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
    4682             :                                                         aItemRect,
    4683             :                                                         CTRL_STATE_SELECTED | ( pData->bEnabled? CTRL_STATE_ENABLED: 0 ),
    4684             :                                                         aVal,
    4685           0 :                                                         OUString() ) )
    4686             :                         {
    4687           0 :                             bDrawItemRect = bHighlight;
    4688             :                         }
    4689             :                     }
    4690             :                     else
    4691           0 :                         bDrawItemRect = bHighlight;
    4692           0 :                     Pop();
    4693             :                 }
    4694           0 :                 if( bDrawItemRect )
    4695             :                 {
    4696           0 :                     if ( bHighlight )
    4697             :                     {
    4698           0 :                         if( pData->bEnabled )
    4699           0 :                             SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
    4700             :                         else
    4701             :                         {
    4702           0 :                             SetFillColor();
    4703           0 :                             oldLineColor = GetLineColor();
    4704           0 :                             SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
    4705           0 :                             bRestoreLineColor = true;
    4706             :                         }
    4707             :                     }
    4708             :                     else
    4709           0 :                         SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
    4710             : 
    4711           0 :                     DrawRect( aItemRect );
    4712             :                 }
    4713           0 :                 pMenu->ImplPaint( this, nScrollerHeight, nStartY, pData, bHighlight );
    4714           0 :                 if( bRestoreLineColor )
    4715           0 :                     SetLineColor( oldLineColor );
    4716             :             }
    4717           0 :             return;
    4718             :         }
    4719             : 
    4720           0 :         nY += pData->aSz.Height();
    4721             :     }
    4722             : }
    4723             : 
    4724           0 : Rectangle MenuFloatingWindow::ImplGetItemRect( sal_uInt16 nPos )
    4725             : {
    4726           0 :     if( ! pMenu )
    4727           0 :         return Rectangle();
    4728             : 
    4729           0 :     Rectangle aRect;
    4730           0 :     Size    aSz = GetOutputSizePixel();
    4731           0 :     long    nStartY = ImplGetStartY();
    4732           0 :     long    nY = nScrollerHeight+nStartY;
    4733           0 :     long    nX = 0;
    4734             : 
    4735           0 :     if ( pMenu->pLogo )
    4736           0 :         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
    4737             : 
    4738           0 :     size_t nCount = pMenu->pItemList->size();
    4739           0 :     for ( size_t n = 0; n < nCount; n++ )
    4740             :     {
    4741           0 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    4742           0 :         if ( n == nPos )
    4743             :         {
    4744             :             DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
    4745           0 :             if ( pData->eType != MENUITEM_SEPARATOR )
    4746             :             {
    4747           0 :                 aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
    4748           0 :                 if ( pData->nBits & MIB_POPUPSELECT )
    4749             :                 {
    4750           0 :                     long nFontHeight = GetTextHeight();
    4751           0 :                     aRect.Right() -= nFontHeight + nFontHeight/4;
    4752             :                 }
    4753             :             }
    4754           0 :             break;
    4755             :         }
    4756           0 :         nY += pData->aSz.Height();
    4757             :     }
    4758           0 :     return aRect;
    4759             : }
    4760             : 
    4761           0 : void MenuFloatingWindow::ImplCursorUpDown( bool bUp, bool bHomeEnd )
    4762             : {
    4763           0 :     if( ! pMenu )
    4764           0 :         return;
    4765             : 
    4766           0 :     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
    4767             : 
    4768           0 :     sal_uInt16 n = nHighlightedItem;
    4769           0 :     if ( n == ITEMPOS_INVALID )
    4770             :     {
    4771           0 :         if ( bUp )
    4772           0 :             n = 0;
    4773             :         else
    4774           0 :             n = pMenu->GetItemCount()-1;
    4775             :     }
    4776             : 
    4777           0 :     sal_uInt16 nLoop = n;
    4778             : 
    4779           0 :     if( bHomeEnd )
    4780             :     {
    4781             :         // absolute positioning
    4782           0 :         if( bUp )
    4783             :         {
    4784           0 :             n = pMenu->GetItemCount();
    4785           0 :             nLoop = n-1;
    4786             :         }
    4787             :         else
    4788             :         {
    4789           0 :             n = (sal_uInt16)-1;
    4790           0 :             nLoop = n+1;
    4791             :         }
    4792             :     }
    4793             : 
    4794           0 :     do
    4795             :     {
    4796           0 :         if ( bUp )
    4797             :         {
    4798           0 :             if ( n )
    4799           0 :                 n--;
    4800             :             else
    4801           0 :                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
    4802           0 :                     n = pMenu->GetItemCount()-1;
    4803             :                 else
    4804           0 :                     break;
    4805             :         }
    4806             :         else
    4807             :         {
    4808           0 :             n++;
    4809           0 :             if ( n >= pMenu->GetItemCount() )
    4810             :             {
    4811           0 :                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
    4812           0 :                     n = 0;
    4813             :                 else
    4814           0 :                     break;
    4815             :             }
    4816             :         }
    4817             : 
    4818           0 :         MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
    4819           0 :         if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
    4820           0 :               && ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
    4821             :         {
    4822             :             // Is selection in visible area?
    4823           0 :             if ( IsScrollMenu() )
    4824             :             {
    4825           0 :                 ChangeHighlightItem( ITEMPOS_INVALID, false );
    4826             : 
    4827           0 :                 while ( n < nFirstEntry )
    4828           0 :                     ImplScroll( true );
    4829             : 
    4830           0 :                 Size aOutSz = GetOutputSizePixel();
    4831             :                 sal_uInt16 nLastVisible;
    4832           0 :                 ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
    4833           0 :                 while ( n > nLastVisible )
    4834             :                 {
    4835           0 :                     ImplScroll( false );
    4836           0 :                     ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
    4837             :                 }
    4838             :             }
    4839           0 :             ChangeHighlightItem( n, false );
    4840           0 :             break;
    4841             :         }
    4842             :     } while ( n != nLoop );
    4843             : }
    4844             : 
    4845           0 : void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
    4846             : {
    4847           0 :     ImplDelData aDelData;
    4848           0 :     ImplAddDel( &aDelData );
    4849             : 
    4850           0 :     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
    4851           0 :     bKeyInput = true;
    4852           0 :     switch ( nCode )
    4853             :     {
    4854             :         case KEY_UP:
    4855             :         case KEY_DOWN:
    4856             :         {
    4857           0 :             ImplCursorUpDown( nCode == KEY_UP );
    4858             :         }
    4859           0 :         break;
    4860             :         case KEY_END:
    4861             :         case KEY_HOME:
    4862             :         {
    4863           0 :             ImplCursorUpDown( nCode == KEY_END, true );
    4864             :         }
    4865           0 :         break;
    4866             :         case KEY_F6:
    4867             :         case KEY_ESCAPE:
    4868             :         {
    4869             :             // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
    4870           0 :             if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
    4871           0 :                 break;
    4872           0 :             if( pMenu )
    4873             :             {
    4874           0 :                 if ( !pMenu->pStartedFrom )
    4875             :                 {
    4876           0 :                     StopExecute();
    4877           0 :                     KillActivePopup();
    4878             :                 }
    4879           0 :                 else if ( pMenu->pStartedFrom->bIsMenuBar )
    4880             :                 {
    4881             :                     // Forward...
    4882           0 :                     ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
    4883             :                 }
    4884             :                 else
    4885             :                 {
    4886           0 :                     StopExecute();
    4887           0 :                     PopupMenu* pPopupMenu = (PopupMenu*)pMenu->pStartedFrom;
    4888           0 :                     MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
    4889           0 :                     pFloat->GrabFocus();
    4890           0 :                     pFloat->KillActivePopup();
    4891           0 :                     pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
    4892             :                 }
    4893             :             }
    4894             :         }
    4895           0 :         break;
    4896             :         case KEY_LEFT:
    4897             :         {
    4898           0 :             if ( pMenu && pMenu->pStartedFrom )
    4899             :             {
    4900           0 :                 StopExecute();
    4901           0 :                 if ( pMenu->pStartedFrom->bIsMenuBar )
    4902             :                 {
    4903             :                     // Forward...
    4904           0 :                     ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
    4905             :                 }
    4906             :                 else
    4907             :                 {
    4908           0 :                     MenuFloatingWindow* pFloat = ((PopupMenu*)pMenu->pStartedFrom)->ImplGetFloatingWindow();
    4909           0 :                     pFloat->GrabFocus();
    4910           0 :                     pFloat->KillActivePopup();
    4911           0 :                     sal_uInt16 highlightItem = pFloat->GetHighlightedItem();
    4912           0 :                     pFloat->ChangeHighlightItem(highlightItem, false);
    4913             :                 }
    4914             :             }
    4915             :         }
    4916           0 :         break;
    4917             :         case KEY_RIGHT:
    4918             :         {
    4919           0 :             if( pMenu )
    4920             :             {
    4921           0 :                 bool bDone = false;
    4922           0 :                 if ( nHighlightedItem != ITEMPOS_INVALID )
    4923             :                 {
    4924           0 :                     MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
    4925           0 :                     if ( pData && pData->pSubMenu )
    4926             :                     {
    4927           0 :                         HighlightChanged( 0 );
    4928           0 :                         bDone = true;
    4929             :                     }
    4930             :                 }
    4931           0 :                 if ( !bDone )
    4932             :                 {
    4933           0 :                     Menu* pStart = pMenu->ImplGetStartMenu();
    4934           0 :                     if ( pStart && pStart->bIsMenuBar )
    4935             :                     {
    4936             :                         // Forward...
    4937           0 :                         pStart->ImplGetWindow()->KeyInput( rKEvent );
    4938             :                     }
    4939             :                 }
    4940             :             }
    4941             :         }
    4942           0 :         break;
    4943             :         case KEY_RETURN:
    4944             :         {
    4945           0 :             if( pMenu )
    4946             :             {
    4947           0 :                 MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
    4948           0 :                 if ( pData && pData->bEnabled )
    4949             :                 {
    4950           0 :                     if ( pData->pSubMenu )
    4951           0 :                         HighlightChanged( 0 );
    4952             :                     else
    4953           0 :                         EndExecute();
    4954             :                 }
    4955             :                 else
    4956           0 :                     StopExecute();
    4957             :             }
    4958             :         }
    4959           0 :         break;
    4960             :         case KEY_MENU:
    4961             :         {
    4962           0 :             if( pMenu )
    4963             :             {
    4964           0 :                 Menu* pStart = pMenu->ImplGetStartMenu();
    4965           0 :                 if ( pStart && pStart->bIsMenuBar )
    4966             :                 {
    4967             :                     // Forward...
    4968           0 :                     pStart->ImplGetWindow()->KeyInput( rKEvent );
    4969             :                 }
    4970             :             }
    4971             :         }
    4972           0 :         break;
    4973             :         default:
    4974             :         {
    4975           0 :             sal_Unicode nCharCode = rKEvent.GetCharCode();
    4976           0 :             sal_uInt16 nPos = 0;
    4977           0 :             sal_uInt16 nDuplicates = 0;
    4978           0 :             MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
    4979           0 :             if ( pData )
    4980             :             {
    4981           0 :                 if ( pData->pSubMenu || nDuplicates > 1 )
    4982             :                 {
    4983           0 :                     ChangeHighlightItem( nPos, false );
    4984           0 :                     HighlightChanged( 0 );
    4985             :                 }
    4986             :                 else
    4987             :                 {
    4988           0 :                     nHighlightedItem = nPos;
    4989           0 :                     EndExecute();
    4990             :                 }
    4991             :             }
    4992             :             else
    4993           0 :                 FloatingWindow::KeyInput( rKEvent );
    4994             :         }
    4995             :     }
    4996             :     // #105474# check if menu window was not destroyed
    4997           0 :     if ( !aDelData.IsDead() )
    4998             :     {
    4999           0 :         ImplRemoveDel( &aDelData );
    5000           0 :         bKeyInput = false;
    5001           0 :     }
    5002           0 : }
    5003             : 
    5004           7 : void MenuFloatingWindow::Paint( const Rectangle& )
    5005             : {
    5006           7 :     if( ! pMenu )
    5007           7 :         return;
    5008             : 
    5009           7 :     if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
    5010             :     {
    5011           0 :         SetClipRegion();
    5012           0 :         long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
    5013           0 :         Size aPxSize( GetOutputSizePixel() );
    5014           0 :         aPxSize.Width() -= nX;
    5015           0 :         ImplControlValue aVal( pMenu->nTextPos-GUTTERBORDER );
    5016             :         DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
    5017             :                            Rectangle( Point( nX, 0 ), aPxSize ),
    5018             :                            CTRL_STATE_ENABLED,
    5019             :                            aVal,
    5020           0 :                            OUString() );
    5021           0 :         ImplInitClipRegion();
    5022             :     }
    5023           7 :     if ( IsScrollMenu() )
    5024             :     {
    5025           0 :         ImplDrawScroller( true );
    5026           0 :         ImplDrawScroller( false );
    5027             :     }
    5028           7 :     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
    5029           7 :     pMenu->ImplPaint( this, nScrollerHeight, ImplGetStartY() );
    5030           7 :     if ( nHighlightedItem != ITEMPOS_INVALID )
    5031           0 :         HighlightItem( nHighlightedItem, true );
    5032             : }
    5033             : 
    5034           0 : void MenuFloatingWindow::ImplDrawScroller( bool bUp )
    5035             : {
    5036           0 :     if( ! pMenu )
    5037           0 :         return;
    5038             : 
    5039           0 :     SetClipRegion();
    5040             : 
    5041           0 :     Size aOutSz = GetOutputSizePixel();
    5042           0 :     long nY = bUp ? 0 : ( aOutSz.Height() - nScrollerHeight );
    5043           0 :     long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
    5044           0 :     Rectangle aRect( Point( nX, nY ), Size( aOutSz.Width()-nX, nScrollerHeight ) );
    5045             : 
    5046           0 :     DecorationView aDecoView( this );
    5047           0 :     SymbolType eSymbol = bUp ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN;
    5048             : 
    5049           0 :     sal_uInt16 nStyle = 0;
    5050           0 :     if ( ( bUp && !bScrollUp ) || ( !bUp && !bScrollDown ) )
    5051           0 :         nStyle |= SYMBOL_DRAW_DISABLE;
    5052             : 
    5053           0 :     aDecoView.DrawSymbol( aRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
    5054             : 
    5055           0 :     ImplInitClipRegion();
    5056             : }
    5057             : 
    5058           0 : void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
    5059             : {
    5060           0 :     sal_uInt16 nId = nHighlightedItem;
    5061           0 :     Menu* pM = pMenu;
    5062           0 :     Window* pW = this;
    5063             : 
    5064             :     // #102618# Get item rect before destroying the window in EndExecute() call
    5065           0 :     Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
    5066             : 
    5067           0 :     if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
    5068             :     {
    5069           0 :         nHighlightedItem = ITEMPOS_INVALID;
    5070           0 :         EndExecute();
    5071           0 :         pW = NULL;
    5072             :     }
    5073             : 
    5074           0 :     if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
    5075           0 :         Window::RequestHelp( rHEvt );
    5076           0 : }
    5077             : 
    5078          24 : void MenuFloatingWindow::StateChanged( StateChangedType nType )
    5079             : {
    5080          24 :     FloatingWindow::StateChanged( nType );
    5081             : 
    5082          24 :     if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
    5083             :     {
    5084           0 :         ImplInitMenuWindow( this, false, false );
    5085           0 :         Invalidate();
    5086             :     }
    5087          24 : }
    5088             : 
    5089           0 : void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
    5090             : {
    5091           0 :     FloatingWindow::DataChanged( rDCEvt );
    5092             : 
    5093           0 :     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
    5094           0 :          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
    5095           0 :          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
    5096           0 :           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
    5097             :     {
    5098           0 :         ImplInitMenuWindow( this, false, false );
    5099           0 :         Invalidate();
    5100             :     }
    5101           0 : }
    5102             : 
    5103           0 : void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
    5104             : {
    5105           0 :     if ( rCEvt.GetCommand() == COMMAND_WHEEL )
    5106             :     {
    5107           0 :         const CommandWheelData* pData = rCEvt.GetWheelData();
    5108           0 :         if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
    5109             :         {
    5110             : //          ImplCursorUpDown( pData->GetDelta() > 0L );
    5111           0 :             ImplScroll( pData->GetDelta() > 0L );
    5112           0 :             MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
    5113             :         }
    5114             :     }
    5115           0 : }
    5116             : 
    5117           0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuFloatingWindow::CreateAccessible()
    5118             : {
    5119           0 :     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
    5120             : 
    5121           0 :     if ( pMenu && !pMenu->pStartedFrom )
    5122           0 :         xAcc = pMenu->GetAccessible();
    5123             : 
    5124           0 :     return xAcc;
    5125             : }
    5126             : 
    5127        2042 : MenuBarWindow::MenuBarWindow( Window* pParent ) :
    5128             :     Window( pParent, 0 ),
    5129             :     aCloser( this ),
    5130             :     aFloatBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
    5131        2042 :     aHideBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE )
    5132             : {
    5133        2042 :     SetType( WINDOW_MENUBARWINDOW );
    5134        2042 :     pMenu = NULL;
    5135        2042 :     pActivePopup = NULL;
    5136        2042 :     nSaveFocusId = 0;
    5137        2042 :     nHighlightedItem = ITEMPOS_INVALID;
    5138        2042 :     nRolloveredItem = ITEMPOS_INVALID;
    5139        2042 :     mbAutoPopup = true;
    5140        2042 :     nSaveFocusId = 0;
    5141        2042 :     bIgnoreFirstMove = true;
    5142        2042 :     bStayActive = false;
    5143             : 
    5144        2042 :     ResMgr* pResMgr = ImplGetResMgr();
    5145             : 
    5146        2042 :     if( pResMgr )
    5147             :     {
    5148        2042 :         BitmapEx aBitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
    5149        2042 :         aCloser.maImage = Image( aBitmap );
    5150             : 
    5151        2042 :         aCloser.SetOutStyle( TOOLBOX_STYLE_FLAT );
    5152        2042 :         aCloser.SetBackground();
    5153        2042 :         aCloser.SetPaintTransparent( true );
    5154        2042 :         aCloser.SetParentClipMode( PARENTCLIPMODE_NOCLIP );
    5155             : 
    5156        2042 :         aCloser.InsertItem( IID_DOCUMENTCLOSE, aCloser.maImage, 0 );
    5157        2042 :         aCloser.SetSelectHdl( LINK( this, MenuBarWindow, CloserHdl ) );
    5158        2042 :         aCloser.AddEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
    5159        2042 :         aCloser.SetQuickHelpText( IID_DOCUMENTCLOSE, ResId(SV_HELPTEXT_CLOSEDOCUMENT, *pResMgr).toString() );
    5160             : 
    5161        2042 :         aFloatBtn.SetClickHdl( LINK( this, MenuBarWindow, FloatHdl ) );
    5162        2042 :         aFloatBtn.SetSymbol( SYMBOL_FLOAT );
    5163        2042 :         aFloatBtn.SetQuickHelpText( ResId(SV_HELPTEXT_RESTORE, *pResMgr).toString() );
    5164             : 
    5165        2042 :         aHideBtn.SetClickHdl( LINK( this, MenuBarWindow, HideHdl ) );
    5166        2042 :         aHideBtn.SetSymbol( SYMBOL_HIDE );
    5167        2042 :         aHideBtn.SetQuickHelpText( ResId(SV_HELPTEXT_MINIMIZE, *pResMgr).toString() );
    5168             :     }
    5169             : 
    5170        2042 :     ImplInitStyleSettings();
    5171             : 
    5172        2042 :     AddEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
    5173        2042 : }
    5174             : 
    5175        6102 : MenuBarWindow::~MenuBarWindow()
    5176             : {
    5177        2034 :     aCloser.RemoveEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
    5178        2034 :     RemoveEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
    5179        4068 : }
    5180             : 
    5181        2043 : void MenuBarWindow::SetMenu( MenuBar* pMen )
    5182             : {
    5183        2043 :     pMenu = pMen;
    5184        2043 :     KillActivePopup();
    5185        2043 :     nHighlightedItem = ITEMPOS_INVALID;
    5186        2043 :     ImplInitMenuWindow( this, true, true );
    5187        2043 :     if ( pMen )
    5188             :     {
    5189        2043 :         aCloser.ShowItem( IID_DOCUMENTCLOSE, pMen->HasCloser() );
    5190        2043 :         aCloser.Show( pMen->HasCloser() || !m_aAddButtons.empty() );
    5191        2043 :         aFloatBtn.Show( pMen->HasFloatButton() );
    5192        2043 :         aHideBtn.Show( pMen->HasHideButton() );
    5193             :     }
    5194        2043 :     Invalidate();
    5195             : 
    5196             :     // show and connect native menubar
    5197        2043 :     if( pMenu && pMenu->ImplGetSalMenu() )
    5198             :     {
    5199           0 :         if( pMenu->ImplGetSalMenu()->VisibleMenuBar() )
    5200           0 :             ImplGetFrame()->SetMenu( pMenu->ImplGetSalMenu() );
    5201             : 
    5202           0 :         pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
    5203             :     }
    5204        2043 : }
    5205             : 
    5206        2025 : void MenuBarWindow::ShowButtons( bool bClose, bool bFloat, bool bHide )
    5207             : {
    5208        2025 :     aCloser.ShowItem( IID_DOCUMENTCLOSE, bClose );
    5209        2025 :     aCloser.Show( bClose || ! m_aAddButtons.empty() );
    5210        2025 :     aFloatBtn.Show( bFloat );
    5211        2025 :     aHideBtn.Show( bHide );
    5212        2025 :     Resize();
    5213        2025 : }
    5214             : 
    5215        2211 : Size MenuBarWindow::MinCloseButtonSize()
    5216             : {
    5217        2211 :     return aCloser.getMinSize();
    5218             : }
    5219             : 
    5220           0 : IMPL_LINK_NOARG(MenuBarWindow, CloserHdl)
    5221             : {
    5222           0 :     if( ! pMenu )
    5223           0 :         return 0;
    5224             : 
    5225           0 :     if( aCloser.GetCurItemId() == IID_DOCUMENTCLOSE )
    5226             :     {
    5227             :         // #i106052# call close hdl asynchronously to ease handler implementation
    5228             :         // this avoids still being in the handler while the DecoToolBox already
    5229             :         // gets destroyed
    5230           0 :         Application::PostUserEvent( ((MenuBar*)pMenu)->GetCloserHdl(), pMenu );
    5231             :     }
    5232             :     else
    5233             :     {
    5234           0 :         std::map<sal_uInt16,AddButtonEntry>::iterator it = m_aAddButtons.find( aCloser.GetCurItemId() );
    5235           0 :         if( it != m_aAddButtons.end() )
    5236             :         {
    5237             :             MenuBar::MenuBarButtonCallbackArg aArg;
    5238           0 :             aArg.nId = it->first;
    5239           0 :             aArg.bHighlight = (aCloser.GetHighlightItemId() == it->first);
    5240           0 :             aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
    5241           0 :             return it->second.m_aSelectLink.Call( &aArg );
    5242             :         }
    5243             :     }
    5244           0 :     return 0;
    5245             : }
    5246             : 
    5247       37486 : IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent*, pEvent )
    5248             : {
    5249       18743 :     if( ! pMenu )
    5250           0 :         return 0;
    5251             : 
    5252             :     MenuBar::MenuBarButtonCallbackArg aArg;
    5253       18743 :     aArg.nId = 0xffff;
    5254       18743 :     aArg.bHighlight = (pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT);
    5255       18743 :     aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
    5256       18743 :     if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT )
    5257           0 :         aArg.nId = aCloser.GetHighlightItemId();
    5258       18743 :     else if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHTOFF )
    5259             :     {
    5260           0 :         sal_uInt16 nPos = static_cast< sal_uInt16 >(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
    5261           0 :         aArg.nId = aCloser.GetItemId( nPos );
    5262             :     }
    5263       18743 :     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
    5264       18743 :     if( it != m_aAddButtons.end() )
    5265             :     {
    5266           0 :         it->second.m_aHighlightLink.Call( &aArg );
    5267             :     }
    5268       18743 :     return 0;
    5269             : }
    5270             : 
    5271       15350 : IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent*, pEvent )
    5272             : {
    5273        7675 :     if( ! pMenu )
    5274           0 :         return 0;
    5275             : 
    5276        7675 :     if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
    5277        2794 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
    5278        4881 :     else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
    5279           0 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
    5280        7675 :     return 0;
    5281             : }
    5282             : 
    5283           0 : IMPL_LINK_NOARG(MenuBarWindow, FloatHdl)
    5284             : {
    5285           0 :     return pMenu ? ((MenuBar*)pMenu)->GetFloatButtonClickHdl().Call( pMenu ) : 0;
    5286             : }
    5287             : 
    5288           0 : IMPL_LINK_NOARG(MenuBarWindow, HideHdl)
    5289             : {
    5290           0 :     return pMenu ? ((MenuBar*)pMenu)->GetHideButtonClickHdl().Call( pMenu ) : 0;
    5291             : }
    5292             : 
    5293          24 : void MenuBarWindow::ImplCreatePopup( bool bPreSelectFirst )
    5294             : {
    5295          24 :     MenuItemData* pItemData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
    5296          24 :     if ( pItemData )
    5297             :     {
    5298           8 :         bIgnoreFirstMove = true;
    5299           8 :         if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
    5300             :         {
    5301           0 :             KillActivePopup();
    5302             :         }
    5303           8 :         if ( pItemData->bEnabled && pItemData->pSubMenu && ( nHighlightedItem != ITEMPOS_INVALID ) && ( pItemData->pSubMenu != pActivePopup ) )
    5304             :         {
    5305           8 :             pActivePopup = (PopupMenu*)pItemData->pSubMenu;
    5306           8 :             long nX = 0;
    5307           8 :             MenuItemData* pData = 0;
    5308          19 :             for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
    5309             :             {
    5310          11 :                 pData = pMenu->GetItemList()->GetDataFromPos( n );
    5311          11 :                 nX += pData->aSz.Width();
    5312             :             }
    5313           8 :             pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
    5314           8 :             Point aItemTopLeft( nX, 0 );
    5315           8 :             Point aItemBottomRight( aItemTopLeft );
    5316           8 :             aItemBottomRight.X() += pData->aSz.Width();
    5317             : 
    5318             :             // the menu bar could have height 0 in fullscreen mode:
    5319             :             // so do not use always WindowHeight, as ItemHeight < WindowHeight.
    5320           8 :             if ( GetSizePixel().Height() )
    5321             :             {
    5322             :                 // #107747# give menuitems the height of the menubar
    5323           8 :                 aItemBottomRight.Y() += GetOutputSizePixel().Height()-1;
    5324             :             }
    5325             : 
    5326             :             // ImplExecute is not modal...
    5327             :             // #99071# do not grab the focus, otherwise it will be restored to the menubar
    5328             :             // when the frame is reactivated later
    5329             :             //GrabFocus();
    5330           8 :             pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_NOHORZPLACEMENT, pMenu, bPreSelectFirst );
    5331           8 :             if ( pActivePopup )
    5332             :             {
    5333             :                 // does not have a window, if aborted before or if there are no entries
    5334           8 :                 if ( pActivePopup->ImplGetFloatingWindow() )
    5335           8 :                     pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
    5336             :                 else
    5337           0 :                     pActivePopup = NULL;
    5338             :             }
    5339             :         }
    5340             :     }
    5341          24 : }
    5342             : 
    5343        4085 : void MenuBarWindow::KillActivePopup()
    5344             : {
    5345        4085 :     if ( pActivePopup )
    5346             :     {
    5347           8 :         if( pActivePopup->pWindow != NULL )
    5348           8 :             if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
    5349        4085 :                 return; // kill it later
    5350             : 
    5351           8 :         if ( pActivePopup->bInCallback )
    5352           0 :             pActivePopup->bCanceled = true;
    5353             : 
    5354           8 :         pActivePopup->bInCallback = true;
    5355           8 :         pActivePopup->Deactivate();
    5356           8 :         pActivePopup->bInCallback = false;
    5357             :         // check for pActivePopup, if stopped by deactivate...
    5358           8 :         if ( pActivePopup->ImplGetWindow() )
    5359             :         {
    5360           8 :             pActivePopup->ImplGetFloatingWindow()->StopExecute();
    5361           8 :             pActivePopup->ImplGetFloatingWindow()->doShutdown();
    5362           8 :             pActivePopup->pWindow->doLazyDelete();
    5363           8 :             pActivePopup->pWindow = NULL;
    5364             :         }
    5365           8 :         pActivePopup = 0;
    5366             :     }
    5367             : }
    5368             : 
    5369           0 : void MenuBarWindow::PopupClosed( Menu* pPopup )
    5370             : {
    5371           0 :     if ( pPopup == pActivePopup )
    5372             :     {
    5373           0 :         KillActivePopup();
    5374           0 :         ChangeHighlightItem( ITEMPOS_INVALID, false, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, false );
    5375             :     }
    5376           0 : }
    5377             : 
    5378           0 : void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
    5379             : {
    5380           0 :     mbAutoPopup = true;
    5381           0 :     sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
    5382           0 :     if ( ( nEntry != ITEMPOS_INVALID ) && !pActivePopup )
    5383             :     {
    5384           0 :         ChangeHighlightItem( nEntry, false );
    5385             :     }
    5386             :     else
    5387             :     {
    5388           0 :         KillActivePopup();
    5389           0 :         ChangeHighlightItem( ITEMPOS_INVALID, false );
    5390             :     }
    5391           0 : }
    5392             : 
    5393           0 : void MenuBarWindow::MouseButtonUp( const MouseEvent& )
    5394             : {
    5395           0 : }
    5396             : 
    5397           0 : void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
    5398             : {
    5399           0 :     if ( rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
    5400           0 :         return;
    5401             : 
    5402           0 :     if ( rMEvt.IsLeaveWindow() )
    5403             :     {
    5404           0 :         if ( nRolloveredItem != ITEMPOS_INVALID && nRolloveredItem != nHighlightedItem )
    5405           0 :             HighlightItem( nRolloveredItem, false );
    5406             : 
    5407           0 :         nRolloveredItem = ITEMPOS_INVALID;
    5408           0 :         return;
    5409             :     }
    5410             : 
    5411           0 :     sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
    5412           0 :     if ( nHighlightedItem == ITEMPOS_INVALID )
    5413             :     {
    5414           0 :         if ( nRolloveredItem != nEntry  )
    5415             :         {
    5416           0 :             if ( nRolloveredItem != ITEMPOS_INVALID )
    5417           0 :                 HighlightItem( nRolloveredItem, false );
    5418             : 
    5419           0 :             nRolloveredItem = nEntry;
    5420           0 :             HighlightItem( nRolloveredItem, true );
    5421             :         }
    5422           0 :         return;
    5423             :     }
    5424           0 :     nRolloveredItem = nEntry;
    5425             : 
    5426           0 :     if( bIgnoreFirstMove )
    5427             :     {
    5428           0 :         bIgnoreFirstMove = false;
    5429           0 :         return;
    5430             :     }
    5431             : 
    5432           0 :     if ( ( nEntry != ITEMPOS_INVALID )
    5433           0 :        && ( nEntry != nHighlightedItem ) )
    5434           0 :         ChangeHighlightItem( nEntry, false );
    5435             : }
    5436             : 
    5437          26 : void MenuBarWindow::ChangeHighlightItem( sal_uInt16 n, bool bSelectEntry, bool bAllowRestoreFocus, bool bDefaultToDocument)
    5438             : {
    5439          26 :     if( ! pMenu )
    5440          26 :         return;
    5441             : 
    5442             :     // #57934# close active popup if applicable, as TH's background storage works.
    5443          26 :     MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
    5444          26 :     if ( pActivePopup && pActivePopup->ImplGetWindow() && ( !pNextData || ( pActivePopup != pNextData->pSubMenu ) ) )
    5445           0 :         KillActivePopup(); // pActivePopup when applicable without pWin, if Rescheduled in  Activate()
    5446             : 
    5447             :     // activate menubar only ones per cycle...
    5448          26 :     bool bJustActivated = false;
    5449          26 :     if ( ( nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
    5450             :     {
    5451          10 :         ImplGetSVData()->maWinData.mbNoDeactivate = true;
    5452          10 :         if( !bStayActive )
    5453             :         {
    5454             :             // #105406# avoid saving the focus when we already have the focus
    5455          10 :             bool bNoSaveFocus = (this == ImplGetSVData()->maWinData.mpFocusWin );
    5456             : 
    5457          10 :             if( nSaveFocusId )
    5458             :             {
    5459           0 :                 if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
    5460             :                 {
    5461             :                     // we didn't clean up last time
    5462           0 :                     Window::EndSaveFocus( nSaveFocusId, false );    // clean up
    5463           0 :                     nSaveFocusId = 0;
    5464           0 :                     if( !bNoSaveFocus )
    5465           0 :                         nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
    5466             :                 }
    5467             :                 else {
    5468             :                     ; // do nothing: we 're activated again from taskpanelist, focus was already saved
    5469             :                 }
    5470             :             }
    5471             :             else
    5472             :             {
    5473          10 :                 if( !bNoSaveFocus )
    5474           8 :                     nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
    5475             :             }
    5476             :         }
    5477             :         else
    5478           0 :             bStayActive = false;
    5479          10 :         pMenu->bInCallback = true;  // set here if Activate overloaded
    5480          10 :         pMenu->Activate();
    5481          10 :         pMenu->bInCallback = false;
    5482          10 :         bJustActivated = true;
    5483             :     }
    5484          16 :     else if ( ( nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
    5485             :     {
    5486          16 :         pMenu->bInCallback = true;
    5487          16 :         pMenu->Deactivate();
    5488          16 :         pMenu->bInCallback = false;
    5489          16 :         ImplGetSVData()->maWinData.mbNoDeactivate = false;
    5490          16 :         if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
    5491             :         {
    5492          16 :             sal_uLong nTempFocusId = nSaveFocusId;
    5493          16 :             nSaveFocusId = 0;
    5494          16 :             Window::EndSaveFocus( nTempFocusId, bAllowRestoreFocus );
    5495             :             // #105406# restore focus to document if we could not save focus before
    5496          16 :             if( bDefaultToDocument && !nTempFocusId && bAllowRestoreFocus )
    5497           2 :                 GrabFocusToDocument();
    5498             :         }
    5499             :     }
    5500             : 
    5501          26 :     if ( nHighlightedItem != ITEMPOS_INVALID )
    5502             :     {
    5503           8 :         if ( nHighlightedItem != nRolloveredItem )
    5504           8 :             HighlightItem( nHighlightedItem, false );
    5505             : 
    5506           8 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
    5507             :     }
    5508             : 
    5509          26 :     nHighlightedItem = (sal_uInt16)n;
    5510             :     DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
    5511          26 :     if ( nHighlightedItem != ITEMPOS_INVALID )
    5512          10 :         HighlightItem( nHighlightedItem, true );
    5513          16 :     else if ( nRolloveredItem != ITEMPOS_INVALID )
    5514           0 :         HighlightItem( nRolloveredItem, true );
    5515          26 :     pMenu->SetHighlightItem(nHighlightedItem);
    5516          26 :     pMenu->ImplCallHighlight(nHighlightedItem);
    5517             : 
    5518          26 :     if( mbAutoPopup )
    5519          24 :         ImplCreatePopup( bSelectEntry );
    5520             : 
    5521             :     // #58935# #73659# Focus, if no popup underneath...
    5522          26 :     if ( bJustActivated && !pActivePopup )
    5523           2 :         GrabFocus();
    5524             : }
    5525             : 
    5526          24 : void MenuBarWindow::HighlightItem( sal_uInt16 nPos, bool bHighlight )
    5527             : {
    5528          24 :     if( ! pMenu )
    5529           0 :         return;
    5530             : 
    5531          24 :     long nX = 0;
    5532          24 :     size_t nCount = pMenu->pItemList->size();
    5533          52 :     for ( size_t n = 0; n < nCount; n++ )
    5534             :     {
    5535          52 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    5536          52 :         if ( n == nPos )
    5537             :         {
    5538          24 :             if ( pData->eType != MENUITEM_SEPARATOR )
    5539             :             {
    5540             :                 // #107747# give menuitems the height of the menubar
    5541          24 :                 Rectangle aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
    5542          24 :                 Push( PUSH_CLIPREGION );
    5543          24 :                 IntersectClipRegion( aRect );
    5544          24 :                 bool bRollover = bHighlight && nPos != nHighlightedItem;
    5545          24 :                 if ( bHighlight )
    5546             :                 {
    5547          16 :                     if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
    5548           0 :                         IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
    5549             :                     {
    5550             :                         // draw background (transparency)
    5551           0 :                         MenubarValue aControlValue;
    5552           0 :                         aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
    5553             : 
    5554           0 :                         if ( !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() )
    5555           0 :                             Erase();
    5556             :                         else
    5557             :                         {
    5558           0 :                             Point tmp(0,0);
    5559           0 :                             Rectangle aBgRegion( tmp, GetOutputSizePixel() );
    5560             :                             DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL,
    5561             :                                     aBgRegion,
    5562             :                                     CTRL_STATE_ENABLED,
    5563             :                                     aControlValue,
    5564           0 :                                     OUString() );
    5565             :                         }
    5566             : 
    5567           0 :                         ImplAddNWFSeparator( this, aControlValue );
    5568             : 
    5569             :                         // draw selected item
    5570           0 :                         ControlState nState = CTRL_STATE_ENABLED;
    5571           0 :                         if ( bRollover )
    5572           0 :                             nState |= CTRL_STATE_ROLLOVER;
    5573             :                         else
    5574           0 :                             nState |= CTRL_STATE_SELECTED;
    5575             :                         DrawNativeControl( CTRL_MENUBAR, PART_MENU_ITEM,
    5576             :                                            aRect,
    5577             :                                            nState,
    5578             :                                            aControlValue,
    5579           0 :                                            OUString() );
    5580             :                     }
    5581             :                     else
    5582             :                     {
    5583          16 :                         if ( bRollover )
    5584           0 :                             SetFillColor( GetSettings().GetStyleSettings().GetMenuBarRolloverColor() );
    5585             :                         else
    5586          16 :                             SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
    5587          16 :                         SetLineColor();
    5588          16 :                         DrawRect( aRect );
    5589             :                     }
    5590             :                 }
    5591             :                 else
    5592             :                 {
    5593           8 :                     if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
    5594             :                     {
    5595           0 :                         MenubarValue aMenubarValue;
    5596           0 :                         aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
    5597             : 
    5598           0 :                         if ( !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() )
    5599           0 :                             Erase( aRect );
    5600             :                         else
    5601             :                         {
    5602             :                             // use full window size to get proper gradient
    5603             :                             // but clip accordingly
    5604           0 :                             Point aPt;
    5605           0 :                             Rectangle aCtrlRect( aPt, GetOutputSizePixel() );
    5606             : 
    5607           0 :                             DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED, aMenubarValue, OUString() );
    5608             :                         }
    5609             : 
    5610           0 :                         ImplAddNWFSeparator( this, aMenubarValue );
    5611             :                     }
    5612             :                     else
    5613           8 :                         Erase( aRect );
    5614             :                 }
    5615          24 :                 Pop();
    5616          24 :                 pMenu->ImplPaint( this, 0, 0, pData, bHighlight, false, bRollover );
    5617             :             }
    5618          24 :             return;
    5619             :         }
    5620             : 
    5621          28 :         nX += pData->aSz.Width();
    5622             :     }
    5623             : }
    5624             : 
    5625           0 : Rectangle MenuBarWindow::ImplGetItemRect( sal_uInt16 nPos )
    5626             : {
    5627           0 :     Rectangle aRect;
    5628           0 :     if( pMenu )
    5629             :     {
    5630           0 :         long nX = 0;
    5631           0 :         size_t nCount = pMenu->pItemList->size();
    5632           0 :         for ( size_t n = 0; n < nCount; n++ )
    5633             :         {
    5634           0 :             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    5635           0 :             if ( n == nPos )
    5636             :             {
    5637           0 :                 if ( pData->eType != MENUITEM_SEPARATOR )
    5638             :                     // #107747# give menuitems the height of the menubar
    5639           0 :                     aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
    5640           0 :                 break;
    5641             :             }
    5642             : 
    5643           0 :             nX += pData->aSz.Width();
    5644             :         }
    5645             :     }
    5646           0 :     return aRect;
    5647             : }
    5648             : 
    5649           0 : void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
    5650             : {
    5651           0 :     if ( !ImplHandleKeyEvent( rKEvent ) )
    5652           0 :         Window::KeyInput( rKEvent );
    5653           0 : }
    5654             : 
    5655           0 : bool MenuBarWindow::ImplHandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
    5656             : {
    5657           0 :     if( ! pMenu )
    5658           0 :         return false;
    5659             : 
    5660           0 :     if ( pMenu->bInCallback )
    5661           0 :         return true;    // swallow
    5662             : 
    5663           0 :     bool bDone = false;
    5664           0 :     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
    5665             : 
    5666           0 :     if( GetParent() )
    5667             :     {
    5668           0 :         if( GetParent()->GetWindow( WINDOW_CLIENT )->IsSystemWindow() )
    5669             :         {
    5670           0 :             SystemWindow *pSysWin = (SystemWindow*)GetParent()->GetWindow( WINDOW_CLIENT );
    5671           0 :             if( pSysWin->GetTaskPaneList() )
    5672           0 :                 if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
    5673           0 :                     return true;
    5674             :         }
    5675             :     }
    5676             : 
    5677           0 :     if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
    5678             :     {
    5679           0 :         mbAutoPopup = ImplGetSVData()->maNWFData.mbOpenMenuOnF10;
    5680           0 :         if ( nHighlightedItem == ITEMPOS_INVALID )
    5681             :         {
    5682           0 :             ChangeHighlightItem( 0, false );
    5683           0 :             GrabFocus();
    5684             :         }
    5685             :         else
    5686             :         {
    5687           0 :             ChangeHighlightItem( ITEMPOS_INVALID, false );
    5688           0 :             nSaveFocusId = 0;
    5689             :         }
    5690           0 :         bDone = true;
    5691             :     }
    5692           0 :     else if ( bFromMenu )
    5693             :     {
    5694           0 :         if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
    5695           0 :             ( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
    5696             :         {
    5697           0 :             sal_uInt16 n = nHighlightedItem;
    5698           0 :             if ( n == ITEMPOS_INVALID )
    5699             :             {
    5700           0 :                 if ( nCode == KEY_LEFT)
    5701           0 :                     n = 0;
    5702             :                 else
    5703           0 :                     n = pMenu->GetItemCount()-1;
    5704             :             }
    5705             : 
    5706             :             // handling gtk like (aka mbOpenMenuOnF10)
    5707             :             // do not highlight an item when opening a sub menu
    5708             :             // unless there already was a higlighted sub menu item
    5709           0 :             bool bWasHighlight = false;
    5710           0 :             if( pActivePopup )
    5711             :             {
    5712           0 :                 MenuFloatingWindow* pSubWindow = dynamic_cast<MenuFloatingWindow*>(pActivePopup->ImplGetWindow());
    5713           0 :                 if( pSubWindow )
    5714           0 :                     bWasHighlight = (pSubWindow->GetHighlightedItem() != ITEMPOS_INVALID);
    5715             :             }
    5716             : 
    5717           0 :             sal_uInt16 nLoop = n;
    5718             : 
    5719           0 :             if( nCode == KEY_HOME )
    5720           0 :                 { n = (sal_uInt16)-1; nLoop = n+1; }
    5721           0 :             if( nCode == KEY_END )
    5722           0 :                 { n = pMenu->GetItemCount(); nLoop = n-1; }
    5723             : 
    5724           0 :             do
    5725             :             {
    5726           0 :                 if ( nCode == KEY_LEFT || nCode == KEY_END )
    5727             :                 {
    5728           0 :                     if ( n )
    5729           0 :                         n--;
    5730             :                     else
    5731           0 :                         n = pMenu->GetItemCount()-1;
    5732             :                 }
    5733           0 :                 if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
    5734             :                 {
    5735           0 :                     n++;
    5736           0 :                     if ( n >= pMenu->GetItemCount() )
    5737           0 :                         n = 0;
    5738             :                 }
    5739             : 
    5740           0 :                 MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
    5741           0 :                 if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
    5742             :                 {
    5743           0 :                     bool bDoSelect = true;
    5744           0 :                     if( ImplGetSVData()->maNWFData.mbOpenMenuOnF10 )
    5745           0 :                         bDoSelect = bWasHighlight;
    5746           0 :                     ChangeHighlightItem( n, bDoSelect );
    5747           0 :                     break;
    5748             :                 }
    5749             :             } while ( n != nLoop );
    5750           0 :             bDone = true;
    5751             :         }
    5752           0 :         else if ( nCode == KEY_RETURN )
    5753             :         {
    5754           0 :             if( pActivePopup ) KillActivePopup();
    5755             :             else
    5756           0 :                 if ( !mbAutoPopup )
    5757             :                 {
    5758           0 :                     ImplCreatePopup( true );
    5759           0 :                     mbAutoPopup = true;
    5760             :                 }
    5761           0 :             bDone = true;
    5762             :         }
    5763           0 :         else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
    5764             :         {
    5765           0 :             if ( !mbAutoPopup )
    5766             :             {
    5767           0 :                 ImplCreatePopup( true );
    5768           0 :                 mbAutoPopup = true;
    5769             :             }
    5770           0 :             bDone = true;
    5771             :         }
    5772           0 :         else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
    5773             :         {
    5774           0 :             if( pActivePopup )
    5775             :             {
    5776             :                 // bring focus to menu bar without any open popup
    5777           0 :                 mbAutoPopup = false;
    5778           0 :                 sal_uInt16 n = nHighlightedItem;
    5779           0 :                 nHighlightedItem = ITEMPOS_INVALID;
    5780           0 :                 bStayActive = true;
    5781           0 :                 ChangeHighlightItem( n, false );
    5782           0 :                 bStayActive = false;
    5783           0 :                 KillActivePopup();
    5784           0 :                 GrabFocus();
    5785             :             }
    5786             :             else
    5787           0 :                 ChangeHighlightItem( ITEMPOS_INVALID, false );
    5788             : 
    5789           0 :             if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
    5790             :             {
    5791             :                 // put focus into document
    5792           0 :                 GrabFocusToDocument();
    5793             :             }
    5794             : 
    5795           0 :             bDone = true;
    5796             :         }
    5797             :     }
    5798             : 
    5799           0 :     if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
    5800             :     {
    5801           0 :         sal_Unicode nCharCode = rKEvent.GetCharCode();
    5802           0 :         if ( nCharCode )
    5803             :         {
    5804             :             sal_uInt16 nEntry, nDuplicates;
    5805           0 :             MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, nHighlightedItem );
    5806           0 :             if ( pData && (nEntry != ITEMPOS_INVALID) )
    5807             :             {
    5808           0 :                 mbAutoPopup = true;
    5809           0 :                 ChangeHighlightItem( nEntry, true );
    5810           0 :                 bDone = true;
    5811             :             }
    5812             :         }
    5813             :     }
    5814           0 :     return bDone;
    5815             : }
    5816             : 
    5817         989 : void MenuBarWindow::Paint( const Rectangle& )
    5818             : {
    5819         989 :     if( ! pMenu )
    5820           0 :         return;
    5821             : 
    5822             :     // no VCL paint if native menus
    5823         989 :     if( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() )
    5824             :     {
    5825           0 :         ImplGetFrame()->DrawMenuBar();
    5826           0 :         return;
    5827             :     }
    5828             : 
    5829         989 :     if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
    5830             :     {
    5831           0 :         MenubarValue aMenubarValue;
    5832           0 :         aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
    5833             : 
    5834           0 :         if ( !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() )
    5835           0 :             Erase();
    5836             :         else
    5837             :         {
    5838           0 :             Point aPt;
    5839           0 :             Rectangle aCtrlRegion( aPt, GetOutputSizePixel() );
    5840             : 
    5841           0 :             DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRegion, CTRL_STATE_ENABLED, aMenubarValue, OUString() );
    5842             :         }
    5843             : 
    5844           0 :         ImplAddNWFSeparator( this, aMenubarValue );
    5845             :     }
    5846         989 :     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
    5847         989 :     pMenu->ImplPaint( this, 0 );
    5848         989 :     if ( nHighlightedItem != ITEMPOS_INVALID )
    5849           6 :         HighlightItem( nHighlightedItem, true );
    5850             : 
    5851             :     // in high contrast mode draw a separating line on the lower edge
    5852        1978 :     if( ! IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) &&
    5853         989 :         GetSettings().GetStyleSettings().GetHighContrastMode() )
    5854             :     {
    5855           0 :         Push( PUSH_LINECOLOR | PUSH_MAPMODE );
    5856           0 :         SetLineColor( Color( COL_WHITE ) );
    5857           0 :         SetMapMode( MapMode( MAP_PIXEL ) );
    5858           0 :         Size aSize = GetSizePixel();
    5859           0 :         DrawLine( Point( 0, aSize.Height()-1 ), Point( aSize.Width()-1, aSize.Height()-1 ) );
    5860           0 :         Pop();
    5861             :     }
    5862             : 
    5863             : }
    5864             : 
    5865        4080 : void MenuBarWindow::Resize()
    5866             : {
    5867        4080 :     Size aOutSz = GetOutputSizePixel();
    5868        4080 :     long n      = aOutSz.Height()-4;
    5869        4080 :     long nX     = aOutSz.Width()-3;
    5870        4080 :     long nY     = 2;
    5871             : 
    5872        4080 :     if ( aCloser.IsVisible() )
    5873             :     {
    5874        2000 :         aCloser.Hide();
    5875        2000 :         aCloser.SetImages( n );
    5876        2000 :         Size aTbxSize( aCloser.CalcWindowSizePixel() );
    5877        2000 :         nX -= aTbxSize.Width();
    5878        2000 :         long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
    5879        2000 :         aCloser.setPosSizePixel( nX, nTbxY, aTbxSize.Width(), aTbxSize.Height() );
    5880        2000 :         nX -= 3;
    5881        2000 :         aCloser.Show();
    5882             :     }
    5883        4080 :     if ( aFloatBtn.IsVisible() )
    5884             :     {
    5885           0 :         nX -= n;
    5886           0 :         aFloatBtn.setPosSizePixel( nX, nY, n, n );
    5887             :     }
    5888        4080 :     if ( aHideBtn.IsVisible() )
    5889             :     {
    5890           0 :         nX -= n;
    5891           0 :         aHideBtn.setPosSizePixel( nX, nY, n, n );
    5892             :     }
    5893             : 
    5894        4080 :     aFloatBtn.SetSymbol( SYMBOL_FLOAT );
    5895        4080 :     aHideBtn.SetSymbol( SYMBOL_HIDE );
    5896             :     //aCloser.SetSymbol( SYMBOL_CLOSE ); //is a toolbox now
    5897             : 
    5898        4080 :     Invalidate();
    5899        4080 : }
    5900             : 
    5901           0 : sal_uInt16 MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
    5902             : {
    5903           0 :     if( pMenu )
    5904             :     {
    5905           0 :         long nX = 0;
    5906           0 :         size_t nCount = pMenu->pItemList->size();
    5907           0 :         for ( size_t n = 0; n < nCount; n++ )
    5908             :         {
    5909           0 :             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
    5910           0 :             if ( pMenu->ImplIsVisible( n ) )
    5911             :             {
    5912           0 :                 nX += pData->aSz.Width();
    5913           0 :                 if ( nX > rMousePos.X() )
    5914           0 :                     return (sal_uInt16)n;
    5915             :             }
    5916             :         }
    5917             :     }
    5918           0 :     return ITEMPOS_INVALID;
    5919             : }
    5920             : 
    5921           0 : void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
    5922             : {
    5923           0 :     sal_uInt16 nId = nHighlightedItem;
    5924           0 :     if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
    5925           0 :         ChangeHighlightItem( ITEMPOS_INVALID, true );
    5926             : 
    5927           0 :     Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
    5928           0 :     if( !ImplHandleHelpEvent( this, pMenu, nId, rHEvt, aHighlightRect ) )
    5929           0 :         Window::RequestHelp( rHEvt );
    5930           0 : }
    5931             : 
    5932        4818 : void MenuBarWindow::StateChanged( StateChangedType nType )
    5933             : {
    5934        4818 :     Window::StateChanged( nType );
    5935             : 
    5936        4818 :     if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) ||
    5937             :          ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
    5938             :     {
    5939           0 :         ImplInitMenuWindow( this, false, true );
    5940           0 :         Invalidate();
    5941             :     }
    5942        4818 :     else if( pMenu )
    5943        4818 :         pMenu->ImplKillLayoutData();
    5944             : 
    5945        4818 : }
    5946             : 
    5947           0 : void MenuBarWindow::ImplLayoutChanged()
    5948             : {
    5949           0 :     if( pMenu )
    5950             :     {
    5951           0 :         ImplInitMenuWindow( this, true, true );
    5952             :         // if the font was changed.
    5953           0 :         long nHeight = pMenu->ImplCalcSize( this ).Height();
    5954             : 
    5955             :         // depending on the native implementation or the displayable flag
    5956             :         // the menubar windows is supressed (ie, height=0)
    5957           0 :         if( !((MenuBar*) pMenu)->IsDisplayable() ||
    5958           0 :             ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
    5959           0 :             nHeight = 0;
    5960             : 
    5961           0 :         setPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
    5962           0 :         GetParent()->Resize();
    5963           0 :         Invalidate();
    5964           0 :         Resize();
    5965           0 :         if( pMenu )
    5966           0 :             pMenu->ImplKillLayoutData();
    5967             :     }
    5968           0 : }
    5969             : 
    5970        2042 : void MenuBarWindow::ImplInitStyleSettings()
    5971             : {
    5972        2042 :     if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
    5973           0 :         IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
    5974             :     {
    5975           0 :         AllSettings aSettings( GetSettings() );
    5976           0 :         ImplGetFrame()->UpdateSettings( aSettings ); // to update persona
    5977           0 :         StyleSettings aStyle( aSettings.GetStyleSettings() );
    5978           0 :         Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
    5979           0 :         if( aHighlightTextColor != Color( COL_TRANSPARENT ) )
    5980             :         {
    5981           0 :             aStyle.SetMenuHighlightTextColor( aHighlightTextColor );
    5982             :         }
    5983           0 :         aSettings.SetStyleSettings( aStyle );
    5984           0 :         OutputDevice::SetSettings( aSettings );
    5985             :     }
    5986        2042 : }
    5987             : 
    5988          18 : void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
    5989             : {
    5990          18 :     Window::DataChanged( rDCEvt );
    5991             : 
    5992          54 :     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
    5993          36 :          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
    5994          36 :          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
    5995          18 :           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
    5996             :     {
    5997           0 :         ImplInitStyleSettings();
    5998           0 :         ImplLayoutChanged();
    5999             :     }
    6000          18 : }
    6001             : 
    6002           8 : void MenuBarWindow::LoseFocus()
    6003             : {
    6004           8 :     if ( !HasChildPathFocus( true ) )
    6005           8 :         ChangeHighlightItem( ITEMPOS_INVALID, false, false );
    6006           8 : }
    6007             : 
    6008           8 : void MenuBarWindow::GetFocus()
    6009             : {
    6010           8 :     if ( nHighlightedItem == ITEMPOS_INVALID )
    6011             :     {
    6012           2 :         mbAutoPopup = false;    // do not open menu when activated by focus handling like taskpane cycling
    6013           2 :         ChangeHighlightItem( 0, false );
    6014             :     }
    6015           8 : }
    6016             : 
    6017          10 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuBarWindow::CreateAccessible()
    6018             : {
    6019          10 :     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
    6020             : 
    6021          10 :     if ( pMenu )
    6022          10 :         xAcc = pMenu->GetAccessible();
    6023             : 
    6024          10 :     return xAcc;
    6025             : }
    6026             : 
    6027           0 : sal_uInt16 MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const OUString& i_rToolTip, sal_uInt16 i_nPos )
    6028             : {
    6029             :     // find first free button id
    6030           0 :     sal_uInt16 nId = IID_DOCUMENTCLOSE;
    6031           0 :     std::map< sal_uInt16, AddButtonEntry >::const_iterator it;
    6032           0 :     if( i_nPos > m_aAddButtons.size() )
    6033           0 :         i_nPos = static_cast<sal_uInt16>(m_aAddButtons.size());
    6034           0 :     do
    6035             :     {
    6036           0 :         nId++;
    6037           0 :         it = m_aAddButtons.find( nId );
    6038           0 :     } while( it != m_aAddButtons.end() && nId < 128 );
    6039             :     DBG_ASSERT( nId < 128, "too many addbuttons in menubar" );
    6040           0 :     AddButtonEntry& rNewEntry = m_aAddButtons[nId];
    6041           0 :     rNewEntry.m_nId = nId;
    6042           0 :     rNewEntry.m_aSelectLink = i_rLink;
    6043           0 :     aCloser.InsertItem( nId, i_rImage, 0, 0 );
    6044           0 :     aCloser.calcMinSize();
    6045           0 :     ShowButtons( aCloser.IsItemVisible( IID_DOCUMENTCLOSE ),
    6046           0 :                  aFloatBtn.IsVisible(),
    6047           0 :                  aHideBtn.IsVisible() );
    6048           0 :     ImplLayoutChanged();
    6049             : 
    6050           0 :     if( pMenu->mpSalMenu )
    6051           0 :         pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
    6052             : 
    6053           0 :     return nId;
    6054             : }
    6055             : 
    6056           0 : void MenuBarWindow::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
    6057             : {
    6058           0 :     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
    6059           0 :     if( it != m_aAddButtons.end() )
    6060           0 :         it->second.m_aHighlightLink = rLink;
    6061           0 : }
    6062             : 
    6063           0 : Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( sal_uInt16 nId )
    6064             : {
    6065           0 :     Rectangle aRect;
    6066           0 :     if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
    6067             :     {
    6068           0 :         if( pMenu->mpSalMenu )
    6069             :         {
    6070           0 :             aRect = pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
    6071           0 :             if( aRect == Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
    6072             :             {
    6073             :                 // system menu button is somewhere but location cannot be determined
    6074           0 :                 return Rectangle();
    6075             :             }
    6076             :         }
    6077             : 
    6078           0 :         if( aRect.IsEmpty() )
    6079             :         {
    6080           0 :             aRect = aCloser.GetItemRect( nId );
    6081           0 :             Point aOffset = aCloser.OutputToScreenPixel( Point() );
    6082           0 :             aRect.Move( aOffset.X(), aOffset.Y() );
    6083             :         }
    6084             :     }
    6085           0 :     return aRect;
    6086             : }
    6087             : 
    6088           0 : void MenuBarWindow::RemoveMenuBarButton( sal_uInt16 nId )
    6089             : {
    6090           0 :     sal_uInt16 nPos = aCloser.GetItemPos( nId );
    6091           0 :     aCloser.RemoveItem( nPos );
    6092           0 :     m_aAddButtons.erase( nId );
    6093           0 :     aCloser.calcMinSize();
    6094           0 :     ImplLayoutChanged();
    6095             : 
    6096           0 :     if( pMenu->mpSalMenu )
    6097           0 :         pMenu->mpSalMenu->RemoveMenuBarButton( nId );
    6098           0 : }
    6099             : 
    6100           0 : bool MenuBarWindow::HandleMenuButtonEvent( sal_uInt16 i_nButtonId )
    6101             : {
    6102           0 :     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
    6103           0 :     if( it != m_aAddButtons.end() )
    6104             :     {
    6105             :         MenuBar::MenuBarButtonCallbackArg aArg;
    6106           0 :         aArg.nId = it->first;
    6107           0 :         aArg.bHighlight = true;
    6108           0 :         aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
    6109           0 :         return it->second.m_aSelectLink.Call( &aArg );
    6110             :     }
    6111           0 :     return false;
    6112             : }
    6113             : 
    6114      358669 : ImplMenuDelData::ImplMenuDelData( const Menu* pMenu )
    6115             : : mpNext( 0 )
    6116      358669 : , mpMenu( 0 )
    6117             : {
    6118      358669 :     if( pMenu )
    6119      358669 :         const_cast< Menu* >( pMenu )->ImplAddDel( *this );
    6120      358669 : }
    6121             : 
    6122      358669 : ImplMenuDelData::~ImplMenuDelData()
    6123             : {
    6124      358669 :     if( mpMenu )
    6125      358669 :         const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
    6126      358669 : }
    6127             : 
    6128             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10