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

Generated by: LCOV version 1.10