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