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