LCOV - code coverage report
Current view: top level - vcl/source/window - menu.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 3193 0.0 %
Date: 2014-04-14 Functions: 0 273 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10