1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: menu.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include "vcl/salinst.hxx"
36 #include "tools/list.hxx"
37 #include "tools/debug.hxx"
38 #include "vcl/svdata.hxx"
39 #include "vcl/svapp.hxx"
40 #include "vcl/mnemonic.hxx"
41 #include "vcl/image.hxx"
42 #include "vcl/event.hxx"
43 #include "vcl/help.hxx"
44 #include "vcl/svids.hrc"
45 #include "vcl/floatwin.hxx"
46 #include "vcl/wrkwin.hxx"
47 #include "vcl/timer.hxx"
48 #include "vcl/sound.hxx"
49 #include "vcl/decoview.hxx"
50 #include "vcl/bitmap.hxx"
52 #include "vcl/menu.hxx"
53 #include "vcl/button.hxx"
54 #include "vcl/gradient.hxx"
55 #include "vcl/i18nhelp.hxx"
56 #include "vcl/taskpanelist.hxx"
57 #include "vcl/window.h"
58 #include "vcl/controllayout.hxx"
59 #include "vcl/toolbox.hxx"
60 #include "tools/stream.hxx"
61 #include "vcl/salmenu.hxx"
62 #include "vcl/salframe.hxx"
63 #include "vcl/dockingarea.hxx"
66 #include <com/sun/star/uno/Reference.h>
67 #include <com/sun/star/i18n/XCharacterClassification.hpp>
68 #include <com/sun/star/lang/XComponent.hpp>
69 #include <com/sun/star/accessibility/XAccessible.hpp>
70 #include <com/sun/star/accessibility/AccessibleRole.hpp>
71 #include <vcl/unowrap.hxx>
73 #include <vcl/unohelp.hxx>
74 #include <vcl/configsettings.hxx>
76 #include "vcl/lazydelete.hxx"
83 struct MenuLayoutData
: public ControlLayoutData
85 std::vector
< USHORT
> m_aLineItemIds
;
86 std::vector
< USHORT
> m_aLineItemPositions
;
87 std::map
< USHORT
, Rectangle
> m_aVisibleItemBoundRects
;
92 using namespace ::com::sun::star
;
97 #define ITEMPOS_INVALID 0xFFFF
100 #define EXTRAITEMHEIGHT 4
103 #define IID_DOCUMENTCLOSE 1
109 // return TRUE if hilite should be executed: left mouse button down
110 // or xwp mouse hook enabled
111 static BOOL
ImplHilite( const MouseEvent
& rMEvt
)
113 static BOOL init
= FALSE
;
114 static HOOKCONFIG hc
;
116 // read XWP settings at program startup
119 ULONG cb
= sizeof(HOOKCONFIG
);
120 memset(&hc
, 0, sizeof(HOOKCONFIG
));
121 rc
= PrfQueryProfileData( HINI_USER
, INIAPP_XWPHOOK
, INIKEY_HOOK_CONFIG
,
125 // check mouse left button
126 if (rMEvt
.GetButtons() == MOUSE_LEFT
)
129 return hc
.fSlidingMenus
;
134 static BOOL
ImplAccelDisabled()
136 // display of accelerator strings may be suppressed via configuration
137 static int nAccelDisabled
= -1;
139 if( nAccelDisabled
== -1 )
142 vcl::SettingsConfigItem::get()->
143 getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Menu" ) ),
144 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuppressAccelerators" ) ) );
145 nAccelDisabled
= aStr
.equalsIgnoreAsciiCaseAscii( "true" ) ? 1 : 0;
147 return (nAccelDisabled
== 1) ? TRUE
: FALSE
;
153 MenuItemType eType
; // MenuItem-Type
154 MenuItemBits nBits
; // MenuItem-Bits
155 Menu
* pSubMenu
; // Pointer auf das SubMenu
156 Menu
* pAutoSubMenu
; // Pointer auf SubMenu aus Resource
157 XubString aText
; // Menu-Text
158 XubString aHelpText
; // Help-String
159 XubString aTipHelpText
; // TipHelp-String (eg, expanded filenames)
160 XubString aCommandStr
; // CommandString
161 XubString aHelpCommandStr
; // Help command string (to reference external help)
162 ULONG nHelpId
; // Help-Id
163 ULONG nUserValue
; // User value
164 Image aImage
; // Image
165 KeyCode aAccelKey
; // Accelerator-Key
166 BOOL bChecked
; // Checked
167 BOOL bEnabled
; // Enabled
168 BOOL bVisible
; // Visible (note: this flag will not override MENU_FLAG_HIDEDISABLEDENTRIES when true)
169 BOOL bIsTemporary
; // Temporary inserted ('No selection possible')
171 long nItemImageAngle
;
172 Size aSz
; // nur temporaer gueltig
173 XubString aAccessibleName
; // accessible name
174 XubString aAccessibleDescription
; // accessible description
176 SalMenuItem
* pSalMenuItem
; // access to native menu
179 pSalMenuItem ( NULL
)
181 MenuItemData( const XubString
& rStr
, const Image
& rImage
) :
184 pSalMenuItem ( NULL
)
189 return bChecked
|| ( nBits
& ( MIB_RADIOCHECK
| MIB_CHECKABLE
| MIB_AUTOCHECK
) );
193 MenuItemData::~MenuItemData()
197 ((PopupMenu
*)pAutoSubMenu
)->pRefAutoSubMenu
= NULL
;
202 ImplGetSVData()->mpDefInst
->DestroyMenuItem( pSalMenuItem
);
205 class MenuItemList
: public List
208 uno::Reference
< i18n::XCharacterClassification
> xCharClass
;
212 MenuItemList() : List( 16, 4 ) {}
215 MenuItemData
* Insert( USHORT nId
, MenuItemType eType
, MenuItemBits nBits
,
216 const XubString
& rStr
, const Image
& rImage
,
217 Menu
* pMenu
, USHORT nPos
);
218 void InsertSeparator( USHORT nPos
);
219 void Remove( USHORT nPos
);
222 MenuItemData
* GetData( USHORT nSVId
, USHORT
& rPos
) const;
223 MenuItemData
* GetData( USHORT nSVId
) const
224 { USHORT nTemp
; return GetData( nSVId
, nTemp
); }
225 MenuItemData
* GetDataFromPos( ULONG nPos
) const
226 { return (MenuItemData
*)List::GetObject( nPos
); }
228 MenuItemData
* SearchItem( xub_Unicode cSelectChar
, KeyCode aKeyCode
, USHORT
& rPos
, USHORT
& nDuplicates
, USHORT nCurrentPos
) const;
229 USHORT
GetItemCount( xub_Unicode cSelectChar
) const;
230 USHORT
GetItemCount( KeyCode aKeyCode
) const;
232 uno::Reference
< i18n::XCharacterClassification
> GetCharClass() const;
237 MenuItemList::~MenuItemList()
239 for ( ULONG n
= Count(); n
; )
241 MenuItemData
* pData
= GetDataFromPos( --n
);
246 MenuItemData
* MenuItemList::Insert( USHORT nId
, MenuItemType eType
,
248 const XubString
& rStr
, const Image
& rImage
,
249 Menu
* pMenu
, USHORT nPos
)
251 MenuItemData
* pData
= new MenuItemData( rStr
, rImage
);
253 pData
->eType
= eType
;
254 pData
->nBits
= nBits
;
255 pData
->pSubMenu
= NULL
;
256 pData
->pAutoSubMenu
= NULL
;
258 pData
->nUserValue
= 0;
259 pData
->bChecked
= FALSE
;
260 pData
->bEnabled
= TRUE
;
261 pData
->bVisible
= TRUE
;
262 pData
->bIsTemporary
= FALSE
;
263 pData
->bMirrorMode
= FALSE
;
264 pData
->nItemImageAngle
= 0;
266 SalItemParams aSalMIData
;
267 aSalMIData
.nId
= nId
;
268 aSalMIData
.eType
= eType
;
269 aSalMIData
.nBits
= nBits
;
270 aSalMIData
.pMenu
= pMenu
;
271 aSalMIData
.aText
= rStr
;
272 aSalMIData
.aImage
= rImage
;
274 // Native-support: returns NULL if not supported
275 pData
->pSalMenuItem
= ImplGetSVData()->mpDefInst
->CreateMenuItem( &aSalMIData
);
277 List::Insert( (void*)pData
, nPos
);
281 void MenuItemList::InsertSeparator( USHORT nPos
)
283 MenuItemData
* pData
= new MenuItemData
;
285 pData
->eType
= MENUITEM_SEPARATOR
;
287 pData
->pSubMenu
= NULL
;
288 pData
->pAutoSubMenu
= NULL
;
290 pData
->nUserValue
= 0;
291 pData
->bChecked
= FALSE
;
292 pData
->bEnabled
= TRUE
;
293 pData
->bVisible
= TRUE
;
294 pData
->bIsTemporary
= FALSE
;
295 pData
->bMirrorMode
= FALSE
;
296 pData
->nItemImageAngle
= 0;
298 SalItemParams aSalMIData
;
300 aSalMIData
.eType
= MENUITEM_SEPARATOR
;
301 aSalMIData
.nBits
= 0;
302 aSalMIData
.pMenu
= NULL
;
303 aSalMIData
.aText
= XubString();
304 aSalMIData
.aImage
= Image();
306 // Native-support: returns NULL if not supported
307 pData
->pSalMenuItem
= ImplGetSVData()->mpDefInst
->CreateMenuItem( &aSalMIData
);
309 List::Insert( (void*)pData
, nPos
);
312 void MenuItemList::Remove( USHORT nPos
)
314 MenuItemData
* pData
= (MenuItemData
*)List::Remove( (ULONG
)nPos
);
319 MenuItemData
* MenuItemList::GetData( USHORT nSVId
, USHORT
& rPos
) const
322 MenuItemData
* pData
= (MenuItemData
*)GetObject( rPos
);
325 if ( pData
->nId
== nSVId
)
329 pData
= (MenuItemData
*)GetObject( rPos
);
335 MenuItemData
* MenuItemList::SearchItem( xub_Unicode cSelectChar
, KeyCode aKeyCode
, USHORT
& rPos
, USHORT
& nDuplicates
, USHORT nCurrentPos
) const
337 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
339 USHORT nListCount
= (USHORT
)Count();
341 // try character code first
342 nDuplicates
= GetItemCount( cSelectChar
); // return number of duplicates
345 for ( rPos
= 0; rPos
< nListCount
; rPos
++)
347 MenuItemData
* pData
= GetDataFromPos( rPos
);
348 if ( pData
->bEnabled
&& rI18nHelper
.MatchMnemonic( pData
->aText
, cSelectChar
) )
350 if( nDuplicates
> 1 && rPos
== nCurrentPos
)
351 continue; // select next entry with the same mnemonic
358 // nothing found, try keycode instead
359 nDuplicates
= GetItemCount( aKeyCode
); // return number of duplicates
364 if( aKeyCode
.GetCode() >= KEY_A
&& aKeyCode
.GetCode() <= KEY_Z
)
365 ascii
= sal::static_int_cast
<char>('A' + (aKeyCode
.GetCode() - KEY_A
));
367 for ( rPos
= 0; rPos
< nListCount
; rPos
++)
369 MenuItemData
* pData
= GetDataFromPos( rPos
);
370 if ( pData
->bEnabled
)
372 USHORT n
= pData
->aText
.Search( '~' );
373 if ( n
!= STRING_NOTFOUND
)
376 xub_Unicode mnUnicode
= pData
->aText
.GetChar(n
+1);
377 Window
* pDefWindow
= ImplGetDefaultWindow();
378 if( (pDefWindow
&& pDefWindow
->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode
, Application::GetSettings().GetUILanguage(), mnKeyCode
)
379 && aKeyCode
.GetCode() == mnKeyCode
.GetCode())
380 || (ascii
&& rI18nHelper
.MatchMnemonic( pData
->aText
, ascii
) ) )
383 if( nDuplicates
> 1 && rPos
== nCurrentPos
)
384 continue; // select next entry with the same mnemonic
396 USHORT
MenuItemList::GetItemCount( xub_Unicode cSelectChar
) const
398 // returns number of entries with same mnemonic
399 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
401 USHORT nItems
= 0, nPos
;
402 for ( nPos
= (USHORT
)Count(); nPos
; )
404 MenuItemData
* pData
= GetDataFromPos( --nPos
);
405 if ( pData
->bEnabled
&& rI18nHelper
.MatchMnemonic( pData
->aText
, cSelectChar
) )
412 USHORT
MenuItemList::GetItemCount( KeyCode aKeyCode
) const
414 // returns number of entries with same mnemonic
415 // uses key codes instead of character codes
416 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
418 if( aKeyCode
.GetCode() >= KEY_A
&& aKeyCode
.GetCode() <= KEY_Z
)
419 ascii
= sal::static_int_cast
<char>('A' + (aKeyCode
.GetCode() - KEY_A
));
421 USHORT nItems
= 0, nPos
;
422 for ( nPos
= (USHORT
)Count(); nPos
; )
424 MenuItemData
* pData
= GetDataFromPos( --nPos
);
425 if ( pData
->bEnabled
)
427 USHORT n
= pData
->aText
.Search( '~' );
428 if ( n
!= STRING_NOTFOUND
)
431 // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
432 // so we have working shortcuts when ascii mnemonics are used
433 Window
* pDefWindow
= ImplGetDefaultWindow();
434 if( (pDefWindow
&& pDefWindow
->ImplGetFrame()->MapUnicodeToKeyCode( pData
->aText
.GetChar(n
+1), Application::GetSettings().GetUILanguage(), mnKeyCode
)
435 && aKeyCode
.GetCode() == mnKeyCode
.GetCode())
436 || ( ascii
&& rI18nHelper
.MatchMnemonic( pData
->aText
, ascii
) ) )
445 uno::Reference
< i18n::XCharacterClassification
> MenuItemList::GetCharClass() const
447 if ( !xCharClass
.is() )
448 ((MenuItemList
*)this)->xCharClass
= vcl::unohelper::CreateCharacterClassification();
454 // ----------------------
455 // - MenuFloatingWindow -
456 // ----------------------
458 class MenuFloatingWindow
: public FloatingWindow
460 friend void Menu::ImplFillLayoutData() const;
461 friend Menu::~Menu();
465 PopupMenu
* pActivePopup
;
466 Timer aHighlightChangedTimer
;
467 Timer aSubmenuCloseTimer
;
471 USHORT nHighlightedItem
; // gehighlightetes/selektiertes Item
473 USHORT nScrollerHeight
;
482 BOOL bIgnoreFirstMove
;
485 DECL_LINK( PopupEnd
, FloatingWindow
* );
486 DECL_LINK( HighlightChanged
, Timer
* );
487 DECL_LINK( SubmenuClose
, Timer
* );
488 DECL_LINK( AutoScroll
, Timer
* );
489 DECL_LINK( ShowHideListener
, VclWindowEvent
* );
491 void StateChanged( StateChangedType nType
);
492 void DataChanged( const DataChangedEvent
& rDCEvt
);
494 Region
ImplCalcClipRegion( BOOL bIncludeLogo
= TRUE
) const;
495 void ImplInitClipRegion();
496 void ImplDrawScroller( BOOL bUp
);
497 using Window::ImplScroll
;
498 void ImplScroll( const Point
& rMousePos
);
499 void ImplScroll( BOOL bUp
);
500 void ImplCursorUpDown( BOOL bUp
, BOOL bHomeEnd
= FALSE
);
501 void ImplHighlightItem( const MouseEvent
& rMEvt
, BOOL bMBDown
);
502 long ImplGetStartY() const;
503 Rectangle
ImplGetItemRect( USHORT nPos
);
506 MenuFloatingWindow( Menu
* pMenu
, Window
* pParent
, WinBits nStyle
);
507 ~MenuFloatingWindow();
511 virtual void MouseMove( const MouseEvent
& rMEvt
);
512 virtual void MouseButtonDown( const MouseEvent
& rMEvt
);
513 virtual void MouseButtonUp( const MouseEvent
& rMEvt
);
514 virtual void KeyInput( const KeyEvent
& rKEvent
);
515 virtual void Command( const CommandEvent
& rCEvt
);
516 virtual void Paint( const Rectangle
& rRect
);
517 virtual void RequestHelp( const HelpEvent
& rHEvt
);
518 virtual void Resize();
520 void SetFocusId( ULONG nId
) { nSaveFocusId
= nId
; }
521 ULONG
GetFocusId() const { return nSaveFocusId
; }
523 void EnableScrollMenu( BOOL b
);
524 BOOL
IsScrollMenu() const { return bScrollMenu
; }
525 USHORT
GetScrollerHeight() const { return nScrollerHeight
; }
528 void StopExecute( ULONG nFocusId
= 0 );
530 void EndExecute( USHORT nSelectId
);
532 PopupMenu
* GetActivePopup() const { return pActivePopup
; }
533 void KillActivePopup( PopupMenu
* pThisOnly
= NULL
);
535 void HighlightItem( USHORT nPos
, BOOL bHighlight
);
536 void ChangeHighlightItem( USHORT n
, BOOL bStartPopupTimer
);
537 USHORT
GetHighlightedItem() const { return nHighlightedItem
; }
539 void SetPosInParent( USHORT nPos
) { nPosInParent
= nPos
; }
540 USHORT
GetPosInParent() const { return nPosInParent
; }
542 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> CreateAccessible();
545 // To get the transparent mouse-over look, the closer is actually a toolbox
546 // overload DataChange to handle style changes correctly
547 class DecoToolBox
: public ToolBox
552 using Window::ImplInit
;
554 DecoToolBox( Window
* pParent
, WinBits nStyle
= 0 );
555 DecoToolBox( Window
* pParent
, const ResId
& rResId
);
558 void DataChanged( const DataChangedEvent
& rDCEvt
);
560 void SetImages( long nMaxHeight
= 0 );
569 DecoToolBox::DecoToolBox( Window
* pParent
, WinBits nStyle
) :
570 ToolBox( pParent
, nStyle
)
574 DecoToolBox::DecoToolBox( Window
* pParent
, const ResId
& rResId
) :
575 ToolBox( pParent
, rResId
)
580 void DecoToolBox::ImplInit()
586 void DecoToolBox::DataChanged( const DataChangedEvent
& rDCEvt
)
588 Window::DataChanged( rDCEvt
);
590 if ( rDCEvt
.GetFlags() & SETTINGS_STYLE
)
598 void DecoToolBox::calcMinSize()
600 ToolBox
aTbx( GetParent() );
601 if( GetItemCount() == 0 )
603 ResMgr
* pResMgr
= ImplGetResMgr();
607 aBitmap
= Bitmap( ResId( SV_RESID_BITMAP_CLOSEDOC
, *pResMgr
) );
608 aTbx
.InsertItem( IID_DOCUMENTCLOSE
, Image( aBitmap
) );
612 USHORT nItems
= GetItemCount();
613 for( USHORT i
= 0; i
< nItems
; i
++ )
615 USHORT nId
= GetItemId( i
);
616 aTbx
.InsertItem( nId
, GetItemImage( nId
) );
619 aTbx
.SetOutStyle( TOOLBOX_STYLE_FLAT
);
620 maMinSize
= aTbx
.CalcWindowSizePixel();
623 Size
DecoToolBox::getMinSize()
628 void DecoToolBox::SetImages( long nMaxHeight
)
630 long border
= getMinSize().Height() - maImage
.GetSizePixel().Height();
632 if( !nMaxHeight
&& lastSize
!= -1 )
633 nMaxHeight
= lastSize
+ border
; // don't change anything if called with 0
635 if( nMaxHeight
< getMinSize().Height() )
636 nMaxHeight
= getMinSize().Height();
638 if( lastSize
!= nMaxHeight
- border
)
640 lastSize
= nMaxHeight
- border
;
642 Color
aEraseColor( 255, 255, 255, 255 );
643 BitmapEx
aBmpExDst( maImage
.GetBitmapEx() );
644 BitmapEx
aBmpExSrc( GetSettings().GetStyleSettings().GetMenuBarColor().IsDark() ?
645 maImageHC
.GetBitmapEx() : aBmpExDst
);
647 aEraseColor
.SetTransparency( 255 );
648 aBmpExDst
.Erase( aEraseColor
);
649 aBmpExDst
.SetSizePixel( Size( lastSize
, lastSize
) );
651 Rectangle
aSrcRect( Point(0,0), maImage
.GetSizePixel() );
652 Rectangle
aDestRect( Point((lastSize
- maImage
.GetSizePixel().Width())/2,
653 (lastSize
- maImage
.GetSizePixel().Height())/2 ),
654 maImage
.GetSizePixel() );
657 aBmpExDst
.CopyPixel( aDestRect
, aSrcRect
, &aBmpExSrc
);
658 SetItemImage( IID_DOCUMENTCLOSE
, Image( aBmpExDst
) );
663 // Eine Basicklasse fuer beide (wegen pActivePopup, Timer, ...) waere nett,
664 // aber dann musste eine 'Container'-Klasse gemacht werden, da von
665 // unterschiedlichen Windows abgeleitet...
666 // In den meisten Funktionen muessen dann sowieso Sonderbehandlungen fuer
667 // MenuBar, PopupMenu gemacht werden, also doch zwei verschiedene Klassen.
669 class MenuBarWindow
: public Window
671 friend class MenuBar
;
675 struct AddButtonEntry
679 Link m_aHighlightLink
;
681 AddButtonEntry() : m_nId( 0 ) {}
685 PopupMenu
* pActivePopup
;
686 USHORT nHighlightedItem
;
689 BOOL bIgnoreFirstMove
;
693 PushButton aFloatBtn
;
696 std::map
< USHORT
, AddButtonEntry
> m_aAddButtons
;
698 void HighlightItem( USHORT nPos
, BOOL bHighlight
);
699 void ChangeHighlightItem( USHORT n
, BOOL bSelectPopupEntry
, BOOL bAllowRestoreFocus
= TRUE
, BOOL bDefaultToDocument
= TRUE
);
701 USHORT
ImplFindEntry( const Point
& rMousePos
) const;
702 void ImplCreatePopup( BOOL bPreSelectFirst
);
703 BOOL
ImplHandleKeyEvent( const KeyEvent
& rKEvent
, BOOL bFromMenu
= TRUE
);
704 Rectangle
ImplGetItemRect( USHORT nPos
);
706 void ImplInitStyleSettings();
708 DECL_LINK( CloserHdl
, PushButton
* );
709 DECL_LINK( FloatHdl
, PushButton
* );
710 DECL_LINK( HideHdl
, PushButton
* );
711 DECL_LINK( ToolboxEventHdl
, VclWindowEvent
* );
712 DECL_LINK( ShowHideListener
, VclWindowEvent
* );
714 void StateChanged( StateChangedType nType
);
715 void DataChanged( const DataChangedEvent
& rDCEvt
);
720 MenuBarWindow( Window
* pParent
);
723 void ShowButtons( BOOL bClose
, BOOL bFloat
, BOOL bHide
);
725 virtual void MouseMove( const MouseEvent
& rMEvt
);
726 virtual void MouseButtonDown( const MouseEvent
& rMEvt
);
727 virtual void MouseButtonUp( const MouseEvent
& rMEvt
);
728 virtual void KeyInput( const KeyEvent
& rKEvent
);
729 virtual void Paint( const Rectangle
& rRect
);
730 virtual void Resize();
731 virtual void RequestHelp( const HelpEvent
& rHEvt
);
733 void SetFocusId( ULONG nId
) { nSaveFocusId
= nId
; }
734 ULONG
GetFocusId() const { return nSaveFocusId
; }
736 void SetMenu( MenuBar
* pMenu
);
737 void KillActivePopup();
738 PopupMenu
* GetActivePopup() const { return pActivePopup
; }
739 void PopupClosed( Menu
* pMenu
);
740 USHORT
GetHighlightedItem() const { return nHighlightedItem
; }
741 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> CreateAccessible();
743 void SetAutoPopup( BOOL bAuto
) { mbAutoPopup
= bAuto
; }
744 void ImplLayoutChanged();
745 Size
MinCloseButtonSize();
747 // add an arbitrary button to the menubar (will appear next to closer)
748 USHORT
AddMenuBarButton( const Image
&, const Link
&, const String
&, USHORT nPos
);
749 void SetMenuBarButtonHighlightHdl( USHORT nId
, const Link
& );
750 Rectangle
GetMenuBarButtonRectPixel( USHORT nId
);
751 void RemoveMenuBarButton( USHORT nId
);
752 bool HandleMenuButtonEvent( USHORT i_nButtonId
);
755 static void ImplAddNWFSeparator( Window
*pThis
, const MenubarValue
& rMenubarValue
)
757 // add a separator if
758 // - we have an adjacent docking area
759 // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
760 if( rMenubarValue
.maTopDockingAreaHeight
&& !ImplGetSVData()->maNWFData
.mbDockingAreaSeparateTB
)
762 // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
764 pThis
->SetLineColor( pThis
->GetSettings().GetStyleSettings().GetSeparatorColor() );
766 Rectangle
aRect( aPt
, pThis
->GetOutputSizePixel() );
767 pThis
->DrawLine( aRect
.BottomLeft(), aRect
.BottomRight() );
771 static void ImplSetMenuItemData( MenuItemData
* pData
)
774 if ( !pData
->aImage
)
775 pData
->eType
= MENUITEM_STRING
;
776 else if ( !pData
->aText
.Len() )
777 pData
->eType
= MENUITEM_IMAGE
;
779 pData
->eType
= MENUITEM_STRINGIMAGE
;
782 static ULONG
ImplChangeTipTimeout( ULONG nTimeout
, Window
*pWindow
)
784 AllSettings
aAllSettings( pWindow
->GetSettings() );
785 HelpSettings
aHelpSettings( aAllSettings
.GetHelpSettings() );
786 ULONG nRet
= aHelpSettings
.GetTipTimeout();
787 aHelpSettings
.SetTipTimeout( nTimeout
);
788 aAllSettings
.SetHelpSettings( aHelpSettings
);
789 pWindow
->SetSettings( aAllSettings
);
793 static BOOL
ImplHandleHelpEvent( Window
* pMenuWindow
, Menu
* pMenu
, USHORT nHighlightedItem
, const HelpEvent
& rHEvt
, const Rectangle
&rHighlightRect
)
801 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
803 MenuItemData
* pItemData
= pMenu
->GetItemList()->GetDataFromPos( nHighlightedItem
);
805 nId
= pItemData
->nId
;
808 if ( ( rHEvt
.GetMode() & HELPMODE_BALLOON
) && pMenuWindow
)
811 if( rHEvt
.KeyboardActivated() )
812 aPos
= rHighlightRect
.Center();
814 aPos
= rHEvt
.GetMousePosPixel();
816 Rectangle
aRect( aPos
, Size() );
817 if( pMenu
->GetHelpText( nId
).Len() )
818 Help::ShowBalloon( pMenuWindow
, aPos
, pMenu
->GetHelpText( nId
) );
821 // give user a chance to read the full filename
822 ULONG oldTimeout
=ImplChangeTipTimeout( 60000, pMenuWindow
);
823 // call always, even when strlen==0 to correctly remove tip
824 Help::ShowQuickHelp( pMenuWindow
, aRect
, pMenu
->GetTipHelpText( nId
) );
825 ImplChangeTipTimeout( oldTimeout
, pMenuWindow
);
829 else if ( ( rHEvt
.GetMode() & HELPMODE_QUICK
) && pMenuWindow
)
831 Point aPos
= rHEvt
.GetMousePosPixel();
832 Rectangle
aRect( aPos
, Size() );
833 // give user a chance to read the full filename
834 ULONG oldTimeout
=ImplChangeTipTimeout( 60000, pMenuWindow
);
835 // call always, even when strlen==0 to correctly remove tip
836 Help::ShowQuickHelp( pMenuWindow
, aRect
, pMenu
->GetTipHelpText( nId
) );
837 ImplChangeTipTimeout( oldTimeout
, pMenuWindow
);
840 else if ( rHEvt
.GetMode() & (HELPMODE_CONTEXT
| HELPMODE_EXTENDED
) )
842 // Ist eine Hilfe in die Applikation selektiert
843 Help
* pHelp
= Application::GetHelp();
846 // Ist eine ID vorhanden, dann Hilfe mit der ID aufrufen, sonst
848 String aCommand
= pMenu
->GetItemCommand( nId
);
849 ULONG nHelpId
= pMenu
->GetHelpId( nId
);
851 if ( aCommand
.Len() )
852 pHelp
->Start( aCommand
, NULL
);
854 pHelp
->Start( nHelpId
, NULL
);
856 pHelp
->Start( OOO_HELP_INDEX
, NULL
);
863 static int ImplGetTopDockingAreaHeight( Window
*pWindow
)
865 // find docking area that is top aligned and return its height
866 // note: dockingareas are direct children of the SystemWindow
869 if( pWindow
->ImplGetFrameWindow() )
871 Window
*pWin
= pWindow
->ImplGetFrameWindow()->GetWindow( WINDOW_FIRSTCHILD
); //mpWindowImpl->mpFirstChild;
872 while( pWin
&& !bDone
)
874 if( pWin
->IsSystemWindow() )
876 pWin
= pWin
->GetWindow( WINDOW_FIRSTCHILD
); //mpWindowImpl->mpFirstChild;
877 while( pWin
&& !bDone
)
879 DockingAreaWindow
*pDockingArea
= dynamic_cast< DockingAreaWindow
* >( pWin
);
880 if( pDockingArea
&& pDockingArea
->GetAlign() == WINDOWALIGN_TOP
)
883 if( pDockingArea
->IsVisible() )
884 height
= pDockingArea
->GetOutputSizePixel().Height();
887 pWin
= pWin
->GetWindow( WINDOW_NEXT
); //mpWindowImpl->mpNext;
892 pWin
= pWin
->GetWindow( WINDOW_NEXT
); //mpWindowImpl->mpNext;
900 DBG_CTOR( Menu
, NULL
);
905 // this constructor makes sure we're creating the native menu
906 // with the correct type (ie, MenuBar vs. PopupMenu)
907 Menu::Menu( BOOL bMenubar
)
909 DBG_CTOR( Menu
, NULL
);
910 bIsMenuBar
= bMenubar
;
916 DBG_DTOR( Menu
, NULL
);
918 vcl::LazyDeletor
<Menu
>::Undelete( this );
920 ImplCallEventListeners( VCLEVENT_OBJECT_DYING
, ITEMPOS_INVALID
);
922 // at the window free the reference to the accessible component
923 // and make sure the MenuFloatingWindow knows about our destruction
926 MenuFloatingWindow
* pFloat
= (MenuFloatingWindow
*)pWindow
;
927 if( pFloat
->pMenu
== this )
928 pFloat
->pMenu
= NULL
;
929 pWindow
->SetAccessible( ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
>() );
932 // dispose accessible components
933 if ( mxAccessible
.is() )
935 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XComponent
> xComponent( mxAccessible
, ::com::sun::star::uno::UNO_QUERY
);
936 if ( xComponent
.is() )
937 xComponent
->dispose();
941 Application::RemoveUserEvent( nEventId
);
949 // Native-support: destroy SalMenu
950 ImplSetSalMenu( NULL
);
953 void Menu::doLazyDelete()
955 vcl::LazyDeletor
<Menu
>::Delete( this );
958 void Menu::ImplInit()
960 mnHighlightedItemPos
= ITEMPOS_INVALID
;
964 //bIsMenuBar = FALSE; // this is now set in the ctor, must not be changed here!!!
966 pItemList
= new MenuItemList
;
976 // Native-support: returns NULL if not supported
977 mpSalMenu
= ImplGetSVData()->mpDefInst
->CreateMenu( bIsMenuBar
);
980 Menu
* Menu::ImplGetStartedFrom() const
985 void Menu::ImplLoadRes( const ResId
& rResId
)
987 ResMgr
* pMgr
= rResId
.GetResMgr();
991 rResId
.SetRT( RSC_MENU
);
994 ULONG nObjMask
= ReadLongRes();
996 if( nObjMask
& RSC_MENU_ITEMS
)
998 ULONG nObjFollows
= ReadLongRes();
999 // MenuItems einfuegen
1000 for( ULONG i
= 0; i
< nObjFollows
; i
++ )
1002 InsertItem( ResId( (RSHEADER_TYPE
*)GetClassRes(), *pMgr
) );
1003 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE
*)GetClassRes() ) );
1007 if( nObjMask
& RSC_MENU_TEXT
)
1009 if( bIsMenuBar
) // Kein Titel im Menubar
1012 aTitleText
= ReadStringRes();
1014 if( nObjMask
& RSC_MENU_DEFAULTITEMID
)
1015 SetDefaultItem( sal::static_int_cast
<USHORT
>(ReadLongRes()) );
1018 void Menu::CreateAutoMnemonics()
1020 MnemonicGenerator aMnemonicGenerator
;
1022 for ( n
= 0; n
< pItemList
->Count(); n
++ )
1024 MenuItemData
* pData
= pItemList
->GetDataFromPos(n
);
1025 if ( ! (pData
->nBits
& MIB_NOSELECT
) )
1026 aMnemonicGenerator
.RegisterMnemonic( pData
->aText
);
1028 for ( n
= 0; n
< pItemList
->Count(); n
++ )
1030 MenuItemData
* pData
= pItemList
->GetDataFromPos(n
);
1031 if ( ! (pData
->nBits
& MIB_NOSELECT
) )
1032 aMnemonicGenerator
.CreateMnemonic( pData
->aText
);
1036 void Menu::Activate()
1039 ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE
, ITEMPOS_INVALID
);
1040 if ( !aActivateHdl
.Call( this ) )
1042 Menu
* pStartMenu
= ImplGetStartMenu();
1043 if ( pStartMenu
&& ( pStartMenu
!= this ) )
1045 pStartMenu
->bInCallback
= TRUE
;
1046 // MT 11/01: Call EventListener here? I don't know...
1047 pStartMenu
->aActivateHdl
.Call( this );
1048 pStartMenu
->bInCallback
= FALSE
;
1051 bInCallback
= FALSE
;
1054 void Menu::Deactivate()
1056 for ( USHORT n
= (USHORT
)pItemList
->Count(); n
; )
1058 MenuItemData
* pData
= pItemList
->GetDataFromPos( --n
);
1059 if ( pData
->bIsTemporary
)
1060 pItemList
->Remove( n
);
1064 Menu
* pStartMenu
= ImplGetStartMenu();
1065 ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE
, ITEMPOS_INVALID
);
1066 if ( !aDeactivateHdl
.Call( this ) )
1068 if ( pStartMenu
&& ( pStartMenu
!= this ) )
1070 pStartMenu
->bInCallback
= TRUE
;
1071 pStartMenu
->aDeactivateHdl
.Call( this );
1072 pStartMenu
->bInCallback
= FALSE
;
1075 bInCallback
= FALSE
;
1077 if ( this == pStartMenu
)
1078 GetpApp()->HideHelpStatusText();
1081 void Menu::Highlight()
1083 Menu
* pStartMenu
= ImplGetStartMenu();
1084 if ( !aHighlightHdl
.Call( this ) )
1086 if ( pStartMenu
&& ( pStartMenu
!= this ) )
1087 pStartMenu
->aHighlightHdl
.Call( this );
1090 if ( GetCurItemId() )
1091 GetpApp()->ShowHelpStatusText( GetHelpText( GetCurItemId() ) );
1094 void Menu::ImplSelect()
1096 MenuItemData
* pData
= GetItemList()->GetData( nSelectedId
);
1097 if ( pData
&& (pData
->nBits
& MIB_AUTOCHECK
) )
1099 BOOL bChecked
= IsItemChecked( nSelectedId
);
1100 if ( pData
->nBits
& MIB_RADIOCHECK
)
1103 CheckItem( nSelectedId
, TRUE
);
1106 CheckItem( nSelectedId
, !bChecked
);
1110 ImplSVData
* pSVData
= ImplGetSVData();
1111 pSVData
->maAppData
.mpActivePopupMenu
= NULL
; // Falls neues Execute im Select()
1112 Application::PostUserEvent( nEventId
, LINK( this, Menu
, ImplCallSelect
) );
1117 ImplCallEventListeners( VCLEVENT_MENU_SELECT
, GetItemPos( GetCurItemId() ) );
1118 if ( !aSelectHdl
.Call( this ) )
1120 Menu
* pStartMenu
= ImplGetStartMenu();
1121 if ( pStartMenu
&& ( pStartMenu
!= this ) )
1123 pStartMenu
->nSelectedId
= nSelectedId
;
1124 pStartMenu
->aSelectHdl
.Call( this );
1129 void Menu::ImplSelectWithStart( Menu
* pSMenu
)
1131 Menu
* pOldStartedFrom
= pStartedFrom
;
1132 pStartedFrom
= pSMenu
;
1133 Menu
* pOldStartedStarted
= pOldStartedFrom
? pOldStartedFrom
->pStartedFrom
: NULL
;
1135 if( pOldStartedFrom
)
1136 pOldStartedFrom
->pStartedFrom
= pOldStartedStarted
;
1137 pStartedFrom
= pOldStartedFrom
;
1140 void Menu::RequestHelp( const HelpEvent
& )
1144 void Menu::ImplCallEventListeners( ULONG nEvent
, USHORT nPos
)
1146 VclMenuEvent
aEvent( this, nEvent
, nPos
);
1148 // This is needed by atk accessibility bridge
1149 if ( nEvent
== VCLEVENT_MENU_HIGHLIGHT
)
1151 ImplGetSVData()->mpApp
->ImplCallEventListeners( &aEvent
);
1154 if ( !maEventListeners
.empty() )
1155 maEventListeners
.Call( &aEvent
);
1160 if ( !maChildEventListeners
.empty() )
1161 maChildEventListeners
.Call( &aEvent
);
1163 pMenu
= ( pMenu
->pStartedFrom
!= pMenu
) ? pMenu
->pStartedFrom
: NULL
;
1167 void Menu::AddEventListener( const Link
& rEventListener
)
1169 maEventListeners
.push_back( rEventListener
);
1172 void Menu::RemoveEventListener( const Link
& rEventListener
)
1174 maEventListeners
.remove( rEventListener
);
1177 // -----------------------------------------------------------------------
1179 //void Menu::AddChildEventListener( const Link& rEventListener )
1181 // mpDummy4_WindowChildEventListeners->push_back( rEventListener );
1184 // -----------------------------------------------------------------------
1186 //void Menu::RemoveChildEventListener( const Link& rEventListener )
1188 // mpDummy4_WindowChildEventListeners->remove( rEventListener );
1191 void Menu::InsertItem( USHORT nItemId
, const XubString
& rStr
, MenuItemBits nItemBits
, USHORT nPos
)
1193 DBG_ASSERT( nItemId
, "Menu::InsertItem(): ItemId == 0" );
1194 DBG_ASSERT( GetItemPos( nItemId
) == MENU_ITEM_NOTFOUND
,
1195 "Menu::InsertItem(): ItemId already exists" );
1197 // if Position > ItemCount, append
1198 if ( nPos
>= (USHORT
)pItemList
->Count() )
1201 // put Item in MenuItemList
1202 MenuItemData
* pData
= pItemList
->Insert( nItemId
, MENUITEM_STRING
,
1203 nItemBits
, rStr
, Image(), this, nPos
);
1205 // update native menu
1206 if( ImplGetSalMenu() && pData
->pSalMenuItem
)
1207 ImplGetSalMenu()->InsertItem( pData
->pSalMenuItem
, nPos
);
1209 Window
* pWin
= ImplGetWindow();
1210 delete mpLayoutData
, mpLayoutData
= NULL
;
1213 ImplCalcSize( pWin
);
1214 if ( pWin
->IsVisible() )
1217 ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM
, nPos
);
1220 void Menu::InsertItem( USHORT nItemId
, const Image
& rImage
,
1221 MenuItemBits nItemBits
, USHORT nPos
)
1223 InsertItem( nItemId
, ImplGetSVEmptyStr(), nItemBits
, nPos
);
1224 SetItemImage( nItemId
, rImage
);
1227 void Menu::InsertItem( USHORT nItemId
,
1228 const XubString
& rStr
, const Image
& rImage
,
1229 MenuItemBits nItemBits
, USHORT nPos
)
1231 InsertItem( nItemId
, rStr
, nItemBits
, nPos
);
1232 SetItemImage( nItemId
, rImage
);
1235 void Menu::InsertItem( const ResId
& rResId
, USHORT nPos
)
1237 ResMgr
* pMgr
= rResId
.GetResMgr();
1243 GetRes( rResId
.SetRT( RSC_MENUITEM
) );
1244 nObjMask
= ReadLongRes();
1247 if ( nObjMask
& RSC_MENUITEM_SEPARATOR
)
1248 bSep
= (BOOL
)ReadShortRes();
1251 if ( nObjMask
& RSC_MENUITEM_ID
)
1252 nItemId
= sal::static_int_cast
<USHORT
>(ReadLongRes());
1254 MenuItemBits nStatus
= 0;
1255 if ( nObjMask
& RSC_MENUITEM_STATUS
)
1256 nStatus
= sal::static_int_cast
<MenuItemBits
>(ReadLongRes());
1259 if ( nObjMask
& RSC_MENUITEM_TEXT
)
1260 aText
= ReadStringRes();
1263 if ( nObjMask
& RSC_MENUITEM_BITMAP
)
1267 Bitmap
aBmp( ResId( (RSHEADER_TYPE
*)GetClassRes(), *pMgr
) );
1269 InsertItem( nItemId
, aText
, aBmp
, nStatus
, nPos
);
1271 InsertItem( nItemId
, aBmp
, nStatus
, nPos
);
1273 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE
*)GetClassRes() ) );
1276 InsertItem( nItemId
, aText
, nStatus
, nPos
);
1278 InsertSeparator( nPos
);
1281 if ( nObjMask
& RSC_MENUITEM_HELPTEXT
)
1283 aHelpText
= ReadStringRes();
1285 SetHelpText( nItemId
, aHelpText
);
1289 if ( nObjMask
& RSC_MENUITEM_HELPID
)
1291 nHelpId
= ReadLongRes();
1293 SetHelpId( nItemId
, nHelpId
);
1296 if( !bSep
/* && SvHelpSettings::HelpText( aHelpText, nHelpId ) */ )
1297 SetHelpText( nItemId
, aHelpText
);
1299 if ( nObjMask
& RSC_MENUITEM_KEYCODE
)
1302 SetAccelKey( nItemId
, KeyCode( ResId( (RSHEADER_TYPE
*)GetClassRes(), *pMgr
) ) );
1303 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE
*)GetClassRes() ) );
1305 if( nObjMask
& RSC_MENUITEM_CHECKED
)
1308 CheckItem( nItemId
, (BOOL
)ReadShortRes() );
1310 if ( nObjMask
& RSC_MENUITEM_DISABLE
)
1313 EnableItem( nItemId
, !(BOOL
)ReadShortRes() );
1315 if ( nObjMask
& RSC_MENUITEM_COMMAND
)
1317 String aCommandStr
= ReadStringRes();
1319 SetItemCommand( nItemId
, aCommandStr
);
1321 if ( nObjMask
& RSC_MENUITEM_MENU
)
1325 MenuItemData
* pData
= GetItemList()->GetData( nItemId
);
1328 PopupMenu
* pSubMenu
= new PopupMenu( ResId( (RSHEADER_TYPE
*)GetClassRes(), *pMgr
) );
1329 pData
->pAutoSubMenu
= pSubMenu
;
1330 // #111060# keep track of this pointer, may be it will be deleted from outside
1331 pSubMenu
->pRefAutoSubMenu
= &pData
->pAutoSubMenu
;
1332 SetPopupMenu( nItemId
, pSubMenu
);
1335 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE
*)GetClassRes() ) );
1337 delete mpLayoutData
, mpLayoutData
= NULL
;
1340 void Menu::InsertSeparator( USHORT nPos
)
1342 // do nothing if its a menu bar
1346 // if position > ItemCount, append
1347 if ( nPos
>= (USHORT
)pItemList
->Count() )
1350 // put separator in item list
1351 pItemList
->InsertSeparator( nPos
);
1353 // update native menu
1354 USHORT itemPos
= nPos
!= MENU_APPEND
? nPos
: (USHORT
)pItemList
->Count() - 1;
1355 MenuItemData
*pData
= pItemList
->GetDataFromPos( itemPos
);
1356 if( ImplGetSalMenu() && pData
&& pData
->pSalMenuItem
)
1357 ImplGetSalMenu()->InsertItem( pData
->pSalMenuItem
, nPos
);
1359 delete mpLayoutData
, mpLayoutData
= NULL
;
1361 ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM
, nPos
);
1364 void Menu::RemoveItem( USHORT nPos
)
1366 BOOL bRemove
= FALSE
;
1368 if ( nPos
< GetItemCount() )
1370 // update native menu
1371 if( ImplGetSalMenu() )
1372 ImplGetSalMenu()->RemoveItem( nPos
);
1374 pItemList
->Remove( nPos
);
1378 Window
* pWin
= ImplGetWindow();
1381 ImplCalcSize( pWin
);
1382 if ( pWin
->IsVisible() )
1385 delete mpLayoutData
, mpLayoutData
= NULL
;
1388 ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM
, nPos
);
1391 void ImplCopyItem( Menu
* pThis
, const Menu
& rMenu
, USHORT nPos
, USHORT nNewPos
,
1394 MenuItemType eType
= rMenu
.GetItemType( nPos
);
1396 if ( eType
== MENUITEM_DONTKNOW
)
1399 if ( eType
== MENUITEM_SEPARATOR
)
1400 pThis
->InsertSeparator( nNewPos
);
1403 USHORT nId
= rMenu
.GetItemId( nPos
);
1405 DBG_ASSERT( pThis
->GetItemPos( nId
) == MENU_ITEM_NOTFOUND
,
1406 "Menu::CopyItem(): ItemId already exists" );
1408 MenuItemData
* pData
= rMenu
.GetItemList()->GetData( nId
);
1410 if ( eType
== MENUITEM_STRINGIMAGE
)
1411 pThis
->InsertItem( nId
, pData
->aText
, pData
->aImage
, pData
->nBits
, nNewPos
);
1412 else if ( eType
== MENUITEM_STRING
)
1413 pThis
->InsertItem( nId
, pData
->aText
, pData
->nBits
, nNewPos
);
1415 pThis
->InsertItem( nId
, pData
->aImage
, pData
->nBits
, nNewPos
);
1417 if ( rMenu
.IsItemChecked( nId
) )
1418 pThis
->CheckItem( nId
, TRUE
);
1419 if ( !rMenu
.IsItemEnabled( nId
) )
1420 pThis
->EnableItem( nId
, FALSE
);
1421 pThis
->SetHelpId( nId
, pData
->nHelpId
);
1422 pThis
->SetHelpText( nId
, pData
->aHelpText
);
1423 pThis
->SetAccelKey( nId
, pData
->aAccelKey
);
1424 pThis
->SetItemCommand( nId
, pData
->aCommandStr
);
1425 pThis
->SetHelpCommand( nId
, pData
->aHelpCommandStr
);
1427 PopupMenu
* pSubMenu
= rMenu
.GetPopupMenu( nId
);
1430 // AutoKopie anlegen
1433 PopupMenu
* pNewMenu
= new PopupMenu( *pSubMenu
);
1434 pThis
->SetPopupMenu( nId
, pNewMenu
);
1435 // SetAutoMenu( pThis, nId, pNewMenu );
1438 pThis
->SetPopupMenu( nId
, pSubMenu
);
1443 void Menu::CopyItem( const Menu
& rMenu
, USHORT nPos
, USHORT nNewPos
)
1445 ImplCopyItem( this, rMenu
, nPos
, nNewPos
);
1450 for ( USHORT i
= GetItemCount(); i
; i
-- )
1454 USHORT
Menu::GetItemCount() const
1456 return (USHORT
)pItemList
->Count();
1459 USHORT
Menu::ImplGetVisibleItemCount() const
1462 for ( USHORT n
= (USHORT
)pItemList
->Count(); n
; )
1464 if ( ImplIsVisible( --n
) )
1470 USHORT
Menu::ImplGetFirstVisible() const
1472 for ( USHORT n
= 0; n
< pItemList
->Count(); n
++ )
1474 if ( ImplIsVisible( n
) )
1477 return ITEMPOS_INVALID
;
1480 USHORT
Menu::ImplGetPrevVisible( USHORT nPos
) const
1482 for ( USHORT n
= nPos
; n
; )
1484 if ( n
&& ImplIsVisible( --n
) )
1487 return ITEMPOS_INVALID
;
1490 USHORT
Menu::ImplGetNextVisible( USHORT nPos
) const
1492 for ( USHORT n
= nPos
+1; n
< pItemList
->Count(); n
++ )
1494 if ( ImplIsVisible( n
) )
1497 return ITEMPOS_INVALID
;
1500 USHORT
Menu::GetItemId( USHORT nPos
) const
1502 MenuItemData
* pData
= pItemList
->GetDataFromPos( nPos
);
1510 USHORT
Menu::GetItemPos( USHORT nItemId
) const
1513 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1518 return MENU_ITEM_NOTFOUND
;
1521 MenuItemType
Menu::GetItemType( USHORT nPos
) const
1523 MenuItemData
* pData
= pItemList
->GetDataFromPos( nPos
);
1526 return pData
->eType
;
1528 return MENUITEM_DONTKNOW
;
1531 USHORT
Menu::GetCurItemId() const
1536 void Menu::SetItemBits( USHORT nItemId
, MenuItemBits nBits
)
1538 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1540 pData
->nBits
= nBits
;
1543 MenuItemBits
Menu::GetItemBits( USHORT nItemId
) const
1545 MenuItemBits nBits
= 0;
1546 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1548 nBits
= pData
->nBits
;
1552 void Menu::SetUserValue( USHORT nItemId
, ULONG nValue
)
1554 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1556 pData
->nUserValue
= nValue
;
1559 ULONG
Menu::GetUserValue( USHORT nItemId
) const
1561 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1562 return pData
? pData
->nUserValue
: 0;
1565 void Menu::SetPopupMenu( USHORT nItemId
, PopupMenu
* pMenu
)
1568 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1570 // Item does not exist -> return NULL
1574 // same menu, nothing to do
1575 if ( (PopupMenu
*)pData
->pSubMenu
== pMenu
)
1579 pData
->pSubMenu
= pMenu
;
1581 // #112023# Make sure pStartedFrom does not point to invalid (old) data
1582 if ( pData
->pSubMenu
)
1583 pData
->pSubMenu
->pStartedFrom
= 0;
1585 // set native submenu
1586 if( ImplGetSalMenu() && pData
->pSalMenuItem
)
1589 ImplGetSalMenu()->SetSubMenu( pData
->pSalMenuItem
, pMenu
->ImplGetSalMenu(), nPos
);
1591 ImplGetSalMenu()->SetSubMenu( pData
->pSalMenuItem
, NULL
, nPos
);
1594 ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED
, nPos
);
1597 PopupMenu
* Menu::GetPopupMenu( USHORT nItemId
) const
1599 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1602 return (PopupMenu
*)(pData
->pSubMenu
);
1607 void Menu::SetAccelKey( USHORT nItemId
, const KeyCode
& rKeyCode
)
1610 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1615 if ( pData
->aAccelKey
== rKeyCode
)
1618 pData
->aAccelKey
= rKeyCode
;
1620 // update native menu
1621 if( ImplGetSalMenu() && pData
->pSalMenuItem
)
1622 ImplGetSalMenu()->SetAccelerator( nPos
, pData
->pSalMenuItem
, rKeyCode
, rKeyCode
.GetName() );
1625 KeyCode
Menu::GetAccelKey( USHORT nItemId
) const
1627 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1630 return pData
->aAccelKey
;
1635 KeyEvent
Menu::GetActivationKey( USHORT nItemId
) const
1638 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1641 USHORT nPos
= pData
->aText
.Search( '~' );
1642 if( nPos
!= STRING_NOTFOUND
&& nPos
< pData
->aText
.Len()-1 )
1645 sal_Unicode cAccel
= pData
->aText
.GetChar( nPos
+1 );
1646 if( cAccel
>= 'a' && cAccel
<= 'z' )
1647 nCode
= KEY_A
+ (cAccel
-'a');
1648 else if( cAccel
>= 'A' && cAccel
<= 'Z' )
1649 nCode
= KEY_A
+ (cAccel
-'A');
1650 else if( cAccel
>= '0' && cAccel
<= '9' )
1651 nCode
= KEY_0
+ (cAccel
-'0');
1653 aRet
= KeyEvent( cAccel
, KeyCode( nCode
, KEY_MOD2
) );
1660 void Menu::CheckItem( USHORT nItemId
, BOOL bCheck
)
1663 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1665 if ( !pData
|| pData
->bChecked
== bCheck
)
1668 // Wenn RadioCheck, dann vorherigen unchecken
1669 if ( bCheck
&& (pData
->nBits
& MIB_AUTOCHECK
) &&
1670 (pData
->nBits
& MIB_RADIOCHECK
) )
1672 MenuItemData
* pGroupData
;
1674 USHORT nItemCount
= GetItemCount();
1675 BOOL bFound
= FALSE
;
1680 pGroupData
= pItemList
->GetDataFromPos( nGroupPos
-1 );
1681 if ( pGroupData
->nBits
& MIB_RADIOCHECK
)
1683 if ( IsItemChecked( pGroupData
->nId
) )
1685 CheckItem( pGroupData
->nId
, FALSE
);
1698 while ( nGroupPos
< nItemCount
)
1700 pGroupData
= pItemList
->GetDataFromPos( nGroupPos
);
1701 if ( pGroupData
->nBits
& MIB_RADIOCHECK
)
1703 if ( IsItemChecked( pGroupData
->nId
) )
1705 CheckItem( pGroupData
->nId
, FALSE
);
1716 pData
->bChecked
= bCheck
;
1718 // update native menu
1719 if( ImplGetSalMenu() )
1720 ImplGetSalMenu()->CheckItem( nPos
, bCheck
);
1722 ImplCallEventListeners( bCheck
? VCLEVENT_MENU_ITEMCHECKED
: VCLEVENT_MENU_ITEMUNCHECKED
, nPos
);
1725 BOOL
Menu::IsItemChecked( USHORT nItemId
) const
1728 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1733 return pData
->bChecked
;
1736 void Menu::EnableItem( USHORT nItemId
, BOOL bEnable
)
1739 MenuItemData
* pItemData
= pItemList
->GetData( nItemId
, nPos
);
1741 if ( pItemData
&& ( pItemData
->bEnabled
!= bEnable
) )
1743 pItemData
->bEnabled
= bEnable
;
1745 Window
* pWin
= ImplGetWindow();
1746 if ( pWin
&& pWin
->IsVisible() )
1748 DBG_ASSERT( bIsMenuBar
, "Menu::EnableItem - Popup visible!" );
1750 ULONG nCount
= pItemList
->Count();
1751 for ( ULONG n
= 0; n
< nCount
; n
++ )
1753 MenuItemData
* pData
= pItemList
->GetDataFromPos( n
);
1756 pWin
->Invalidate( Rectangle( Point( nX
, 0 ), Size( pData
->aSz
.Width(), pData
->aSz
.Height() ) ) );
1759 nX
+= pData
->aSz
.Width();
1762 // update native menu
1763 if( ImplGetSalMenu() )
1764 ImplGetSalMenu()->EnableItem( nPos
, bEnable
);
1766 ImplCallEventListeners( bEnable
? VCLEVENT_MENU_ENABLE
: VCLEVENT_MENU_DISABLE
, nPos
);
1770 BOOL
Menu::IsItemEnabled( USHORT nItemId
) const
1773 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1778 return pData
->bEnabled
;
1781 void Menu::ShowItem( USHORT nItemId
, BOOL bVisible
)
1784 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1786 DBG_ASSERT( !bIsMenuBar
, "Menu::ShowItem - ignored for menu bar entries!" );
1787 if ( !bIsMenuBar
&& pData
&& ( pData
->bVisible
!= bVisible
) )
1789 Window
* pWin
= ImplGetWindow();
1790 if ( pWin
&& pWin
->IsVisible() )
1792 DBG_ASSERT( 0, "Menu::ShowItem - ignored for visible popups!" );
1795 pData
->bVisible
= bVisible
;
1797 // update native menu
1798 // as long as there is no support to hide native menu entries, we just disable them
1799 // TODO: add support to show/hide native menu entries
1800 if( ImplGetSalMenu() )
1801 ImplGetSalMenu()->EnableItem( nPos
, bVisible
);
1805 void Menu::SetItemText( USHORT nItemId
, const XubString
& rStr
)
1808 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1813 if ( !rStr
.Equals( pData
->aText
) )
1815 pData
->aText
= rStr
;
1816 ImplSetMenuItemData( pData
);
1817 // update native menu
1818 if( ImplGetSalMenu() && pData
->pSalMenuItem
)
1819 ImplGetSalMenu()->SetItemText( nPos
, pData
->pSalMenuItem
, rStr
);
1821 Window
* pWin
= ImplGetWindow();
1822 delete mpLayoutData
, mpLayoutData
= NULL
;
1823 if ( pWin
&& IsMenuBar() )
1825 ImplCalcSize( pWin
);
1826 if ( pWin
->IsVisible() )
1830 ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED
, nPos
);
1834 XubString
Menu::GetItemText( USHORT nItemId
) const
1837 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1840 return pData
->aText
;
1842 return ImplGetSVEmptyStr();
1845 void Menu::SetItemImage( USHORT nItemId
, const Image
& rImage
)
1848 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1853 pData
->aImage
= rImage
;
1854 ImplSetMenuItemData( pData
);
1856 // update native menu
1857 if( ImplGetSalMenu() && pData
->pSalMenuItem
)
1858 ImplGetSalMenu()->SetItemImage( nPos
, pData
->pSalMenuItem
, rImage
);
1861 static inline Image
ImplRotImage( const Image
& rImage
, long nAngle10
)
1864 BitmapEx
aBmpEx( rImage
.GetBitmapEx() );
1866 aBmpEx
.Rotate( nAngle10
, COL_WHITE
);
1868 return Image( aBmpEx
);
1871 void Menu::SetItemImageAngle( USHORT nItemId
, long nAngle10
)
1874 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1878 long nDeltaAngle
= (nAngle10
- pData
->nItemImageAngle
) % 3600;
1879 while( nDeltaAngle
< 0 )
1880 nDeltaAngle
+= 3600;
1882 pData
->nItemImageAngle
= nAngle10
;
1883 if( nDeltaAngle
&& !!pData
->aImage
)
1884 pData
->aImage
= ImplRotImage( pData
->aImage
, nDeltaAngle
);
1888 static inline Image
ImplMirrorImage( const Image
& rImage
)
1891 BitmapEx
aBmpEx( rImage
.GetBitmapEx() );
1893 aBmpEx
.Mirror( BMP_MIRROR_HORZ
);
1895 return Image( aBmpEx
);
1898 void Menu::SetItemImageMirrorMode( USHORT nItemId
, BOOL bMirror
)
1901 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
1905 if( ( pData
->bMirrorMode
&& ! bMirror
) ||
1906 ( ! pData
->bMirrorMode
&& bMirror
)
1909 pData
->bMirrorMode
= bMirror
? true : false;
1910 if( !!pData
->aImage
)
1911 pData
->aImage
= ImplMirrorImage( pData
->aImage
);
1916 Image
Menu::GetItemImage( USHORT nItemId
) const
1918 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1921 return pData
->aImage
;
1926 long Menu::GetItemImageAngle( USHORT nItemId
) const
1928 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1931 return pData
->nItemImageAngle
;
1936 BOOL
Menu::GetItemImageMirrorMode( USHORT nItemId
) const
1938 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1941 return pData
->bMirrorMode
;
1946 void Menu::SetItemCommand( USHORT nItemId
, const String
& rCommand
)
1948 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1951 pData
->aCommandStr
= rCommand
;
1954 const XubString
& Menu::GetItemCommand( USHORT nItemId
) const
1956 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1959 return pData
->aCommandStr
;
1961 return ImplGetSVEmptyStr();
1964 void Menu::SetHelpCommand( USHORT nItemId
, const XubString
& rStr
)
1966 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1969 pData
->aHelpCommandStr
= rStr
;
1972 const XubString
& Menu::GetHelpCommand( USHORT nItemId
) const
1974 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1977 return pData
->aHelpCommandStr
;
1979 return ImplGetSVEmptyStr();
1982 void Menu::SetHelpText( USHORT nItemId
, const XubString
& rStr
)
1984 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1987 pData
->aHelpText
= rStr
;
1990 const XubString
& Menu::ImplGetHelpText( USHORT nItemId
) const
1992 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
1996 if ( !pData
->aHelpText
.Len() &&
1997 (( pData
->nHelpId
) || ( pData
->aCommandStr
.Len() )))
1999 Help
* pHelp
= Application::GetHelp();
2002 if ( pData
->aCommandStr
.Len() )
2003 pData
->aHelpText
= pHelp
->GetHelpText( pData
->aCommandStr
, NULL
);
2005 if( !pData
->aHelpText
.Len() && pData
->nHelpId
)
2006 pData
->aHelpText
= pHelp
->GetHelpText( pData
->nHelpId
, NULL
);
2010 return pData
->aHelpText
;
2013 return ImplGetSVEmptyStr();
2016 const XubString
& Menu::GetHelpText( USHORT nItemId
) const
2018 return ImplGetHelpText( nItemId
);
2021 void Menu::SetTipHelpText( USHORT nItemId
, const XubString
& rStr
)
2023 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
2026 pData
->aTipHelpText
= rStr
;
2029 const XubString
& Menu::GetTipHelpText( USHORT nItemId
) const
2031 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
2034 return pData
->aTipHelpText
;
2036 return ImplGetSVEmptyStr();
2039 void Menu::SetHelpId( USHORT nItemId
, ULONG nHelpId
)
2041 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
2044 pData
->nHelpId
= nHelpId
;
2047 ULONG
Menu::GetHelpId( USHORT nItemId
) const
2049 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
2052 return pData
->nHelpId
;
2057 Menu
& Menu::operator=( const Menu
& rMenu
)
2063 USHORT nCount
= rMenu
.GetItemCount();
2064 for ( USHORT i
= 0; i
< nCount
; i
++ )
2065 ImplCopyItem( this, rMenu
, i
, MENU_APPEND
, 1 );
2067 nDefaultItem
= rMenu
.nDefaultItem
;
2068 aActivateHdl
= rMenu
.aActivateHdl
;
2069 aDeactivateHdl
= rMenu
.aDeactivateHdl
;
2070 aHighlightHdl
= rMenu
.aHighlightHdl
;
2071 aSelectHdl
= rMenu
.aSelectHdl
;
2072 aTitleText
= rMenu
.aTitleText
;
2073 bIsMenuBar
= rMenu
.bIsMenuBar
;
2078 BOOL
Menu::ImplIsVisible( USHORT nPos
) const
2080 BOOL bVisible
= TRUE
;
2082 MenuItemData
* pData
= pItemList
->GetDataFromPos( nPos
);
2083 // check general visibility first
2084 if( pData
&& !pData
->bVisible
)
2087 if ( bVisible
&& pData
&& pData
->eType
== MENUITEM_SEPARATOR
)
2089 if( nPos
== 0 ) // no separator should be shown at the very beginning
2093 // always avoid adjacent separators
2094 USHORT nCount
= (USHORT
) pItemList
->Count();
2096 MenuItemData
* pNextData
= NULL
;
2097 // search next visible item
2098 for( n
= nPos
+ 1; n
< nCount
; n
++ )
2100 pNextData
= pItemList
->GetDataFromPos( n
);
2101 if( pNextData
&& pNextData
->bVisible
)
2103 if( pNextData
->eType
== MENUITEM_SEPARATOR
|| ImplIsVisible(n
) )
2107 if( n
== nCount
) // no next visible item
2109 // check for separator
2110 if( pNextData
&& pNextData
->bVisible
&& pNextData
->eType
== MENUITEM_SEPARATOR
)
2115 for( n
= nPos
; n
> 0; n
-- )
2117 pNextData
= pItemList
->GetDataFromPos( n
-1 );
2118 if( pNextData
&& pNextData
->bVisible
)
2120 if( pNextData
->eType
!= MENUITEM_SEPARATOR
&& ImplIsVisible(n
-1) )
2124 if( n
== 0 ) // no previous visible item
2130 // Fuer den Menubar nicht erlaubt, weil ich nicht mitbekomme
2131 // ob dadurch ein Eintrag verschwindet oder wieder da ist.
2132 if ( bVisible
&& !bIsMenuBar
&& ( nMenuFlags
& MENU_FLAG_HIDEDISABLEDENTRIES
) &&
2133 !( nMenuFlags
& MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES
) )
2135 if( !pData
) // e.g. nPos == ITEMPOS_INVALID
2137 else if ( pData
->eType
!= MENUITEM_SEPARATOR
) // separators handled above
2139 // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( TRUE ) );
2140 bVisible
= pData
->bEnabled
; // SubMenus nicht pruefen, weil sie ggf. erst im Activate() gefuellt werden.
2147 BOOL
Menu::IsItemVisible( USHORT nItemId
) const
2149 return IsMenuVisible() && ImplIsVisible( GetItemPos( nItemId
) );
2152 BOOL
Menu::IsItemPosVisible( USHORT nItemPos
) const
2154 return IsMenuVisible() && ImplIsVisible( nItemPos
);
2157 BOOL
Menu::IsMenuVisible() const
2159 return pWindow
&& pWindow
->IsReallyVisible();
2162 BOOL
Menu::ImplIsSelectable( USHORT nPos
) const
2164 BOOL bSelectable
= TRUE
;
2166 MenuItemData
* pData
= pItemList
->GetDataFromPos( nPos
);
2167 // check general visibility first
2168 if ( pData
&& ( pData
->nBits
& MIB_NOSELECT
) )
2169 bSelectable
= FALSE
;
2174 void Menu::SelectItem( USHORT nItemId
)
2177 static_cast<MenuBar
*>(this)->SelectEntry( nItemId
);
2179 static_cast<PopupMenu
*>(this)->SelectEntry( nItemId
);
2182 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> Menu::GetAccessible()
2184 // Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
2185 // overwritten and may contain a disposed object when the initial menubar gets set again. So use the
2186 // mxAccessible member only for sub menus.
2189 for ( sal_uInt16 i
= 0, nCount
= pStartedFrom
->GetItemCount(); i
< nCount
; ++i
)
2191 sal_uInt16 nItemId
= pStartedFrom
->GetItemId( i
);
2192 if ( static_cast< Menu
* >( pStartedFrom
->GetPopupMenu( nItemId
) ) == this )
2194 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> xParent
= pStartedFrom
->GetAccessible();
2197 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
2198 if ( xParentContext
.is() )
2199 return xParentContext
->getAccessibleChild( i
);
2204 else if ( !mxAccessible
.is() )
2206 UnoWrapperBase
* pWrapper
= Application::GetUnoWrapper();
2208 mxAccessible
= pWrapper
->CreateAccessible( this, bIsMenuBar
);
2211 return mxAccessible
;
2214 void Menu::SetAccessible( const ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
>& rxAccessible
)
2216 mxAccessible
= rxAccessible
;
2219 long Menu::ImplGetNativeCheckAndRadioSize( Window
* pWin
, long& rCheckHeight
, long& rRadioHeight
, long &rMaxWidth
) const
2221 rMaxWidth
= rCheckHeight
= rRadioHeight
= 0;
2225 ImplControlValue aVal
;
2226 Region aNativeBounds
;
2227 Region aNativeContent
;
2229 Region
aCtrlRegion( Rectangle( tmp
, Size( 100, 15 ) ) );
2230 if( pWin
->IsNativeControlSupported( CTRL_MENU_POPUP
, PART_MENU_ITEM_CHECK_MARK
) )
2232 if( pWin
->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP
),
2233 ControlPart(PART_MENU_ITEM_CHECK_MARK
),
2235 ControlState(CTRL_STATE_ENABLED
),
2242 rCheckHeight
= aNativeBounds
.GetBoundRect().GetHeight();
2243 rMaxWidth
= aNativeContent
.GetBoundRect().GetWidth();
2246 if( pWin
->IsNativeControlSupported( CTRL_MENU_POPUP
, PART_MENU_ITEM_RADIO_MARK
) )
2248 if( pWin
->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP
),
2249 ControlPart(PART_MENU_ITEM_RADIO_MARK
),
2251 ControlState(CTRL_STATE_ENABLED
),
2258 rRadioHeight
= aNativeBounds
.GetBoundRect().GetHeight();
2259 rMaxWidth
= Max (rMaxWidth
, aNativeContent
.GetBoundRect().GetWidth());
2263 return (rCheckHeight
> rRadioHeight
) ? rCheckHeight
: rRadioHeight
;
2266 Size
Menu::ImplCalcSize( Window
* pWin
)
2268 // | Checked| Image| Text| Accel/Popup|
2270 // Fuer Symbole: nFontHeight x nFontHeight
2271 long nFontHeight
= pWin
->GetTextHeight();
2272 long nExtra
= nFontHeight
/4;
2278 long nMinMenuItemHeight
= nFontHeight
;
2279 long nCheckHeight
= 0, nRadioHeight
= 0;
2280 long nCheckWidth
= 0, nMaxCheckWidth
= 0;
2281 long nMax
= ImplGetNativeCheckAndRadioSize( pWin
, nCheckHeight
, nRadioHeight
, nMaxCheckWidth
);
2282 if( nMax
> nMinMenuItemHeight
)
2283 nMinMenuItemHeight
= nMax
;
2285 // When no native rendering of the checkbox & no image in the menu, we
2286 // have to add some extra space even in the MENU_FLAG_SHOWCHECKIMAGES case
2287 bool bSpaceForCheckbox
= ( nMax
== 0 );
2289 const StyleSettings
& rSettings
= pWin
->GetSettings().GetStyleSettings();
2290 if ( rSettings
.GetUseImagesInMenus() )
2292 nMinMenuItemHeight
= 16;
2293 for ( USHORT i
= (USHORT
)pItemList
->Count(); i
; )
2295 MenuItemData
* pData
= pItemList
->GetDataFromPos( --i
);
2296 if ( ImplIsVisible( i
) && (( pData
->eType
== MENUITEM_IMAGE
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
)))
2298 // we have an icon, don't add the extra space
2299 bSpaceForCheckbox
= false;
2301 Size aImgSz
= pData
->aImage
.GetSizePixel();
2302 if ( aImgSz
.Height() > aMaxImgSz
.Height() )
2303 aMaxImgSz
.Height() = aImgSz
.Height();
2304 if ( aImgSz
.Height() > nMinMenuItemHeight
)
2305 nMinMenuItemHeight
= aImgSz
.Height();
2311 for ( USHORT n
= (USHORT
)pItemList
->Count(); n
; )
2313 MenuItemData
* pData
= pItemList
->GetDataFromPos( --n
);
2315 pData
->aSz
.Height() = 0;
2316 pData
->aSz
.Width() = 0;
2318 if ( ImplIsVisible( n
) )
2323 if ( !bIsMenuBar
&& ( pData
->eType
== MENUITEM_SEPARATOR
) )
2325 DBG_ASSERT( !bIsMenuBar
, "Separator in MenuBar ?! " );
2326 pData
->aSz
.Height() = 4;
2330 if ( !bIsMenuBar
&& ( ( pData
->eType
== MENUITEM_IMAGE
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
) ) )
2332 Size aImgSz
= pData
->aImage
.GetSizePixel();
2333 aImgSz
.Height() += 4; // add a border for native marks
2334 aImgSz
.Width() += 4; // add a border for native marks
2335 if ( aImgSz
.Width() > aMaxImgSz
.Width() )
2336 aMaxImgSz
.Width() = aImgSz
.Width();
2337 if ( aImgSz
.Height() > aMaxImgSz
.Height() )
2338 aMaxImgSz
.Height() = aImgSz
.Height();
2339 if ( aImgSz
.Height() > pData
->aSz
.Height() )
2340 pData
->aSz
.Height() = aImgSz
.Height();
2344 if ( !bIsMenuBar
&& pData
->HasCheck() )
2346 nCheckWidth
= nMaxCheckWidth
;
2347 if ( ( nMenuFlags
& MENU_FLAG_SHOWCHECKIMAGES
) || bSpaceForCheckbox
)
2349 // checks / images take the same place
2350 if( ! ( ( pData
->eType
== MENUITEM_IMAGE
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
) ) )
2351 nWidth
+= nCheckWidth
+ nExtra
* 2;
2356 if ( (pData
->eType
== MENUITEM_STRING
) || (pData
->eType
== MENUITEM_STRINGIMAGE
) )
2358 long nTextWidth
= pWin
->GetCtrlTextWidth( pData
->aText
);
2359 long nTextHeight
= pWin
->GetTextHeight();
2361 // if ( nTextHeight > pData->aSz.Height() )
2362 // pData->aSz.Height() = nTextHeight;
2366 if ( nTextHeight
> pData
->aSz
.Height() )
2367 pData
->aSz
.Height() = nTextHeight
;
2369 pData
->aSz
.Width() = nTextWidth
+ 4*nExtra
;
2370 aSz
.Width() += pData
->aSz
.Width();
2373 pData
->aSz
.Height() = Max( Max( nTextHeight
, pData
->aSz
.Height() ), nMinMenuItemHeight
);
2375 nWidth
+= nTextWidth
;
2379 if ( !bIsMenuBar
&& pData
->aAccelKey
.GetCode() && !ImplAccelDisabled() )
2381 String aName
= pData
->aAccelKey
.GetName();
2382 long nAccWidth
= pWin
->GetTextWidth( aName
);
2383 nAccWidth
+= nExtra
;
2384 nWidth
+= nAccWidth
;
2388 if ( !bIsMenuBar
&& pData
->pSubMenu
)
2390 if ( nFontHeight
> nWidth
)
2391 nWidth
+= nFontHeight
;
2393 pData
->aSz
.Height() = Max( Max( nFontHeight
, pData
->aSz
.Height() ), nMinMenuItemHeight
);
2396 pData
->aSz
.Height() += EXTRAITEMHEIGHT
; // Etwas mehr Abstand:
2399 aSz
.Height() += (long)pData
->aSz
.Height();
2401 if ( nWidth
> nMaxWidth
)
2409 USHORT gfxExtra
= (USHORT
) Max( nExtra
, 7L ); // #107710# increase space between checkmarks/images/text
2410 nCheckPos
= (USHORT
)nExtra
;
2411 if ( ( nMenuFlags
& MENU_FLAG_SHOWCHECKIMAGES
) || bSpaceForCheckbox
)
2413 long nImgOrChkWidth
= 0;
2414 nImagePos
= nCheckPos
;
2415 if( nMax
> 0 ) // NWF case
2416 nImgOrChkWidth
= nMax
+ nExtra
;
2417 else // non NWF case
2418 nImgOrChkWidth
= nFontHeight
/2 + gfxExtra
;
2419 nImgOrChkWidth
= Max( nImgOrChkWidth
, aMaxImgSz
.Width() + gfxExtra
);
2420 nTextPos
= (USHORT
)(nImagePos
+ nImgOrChkWidth
);
2424 nImagePos
= nCheckPos
;
2425 nTextPos
= (USHORT
)(nImagePos
+ Max( aMaxImgSz
.Width(), nCheckWidth
));
2427 nTextPos
= nTextPos
+ gfxExtra
;
2429 aSz
.Width() = nTextPos
+ nMaxWidth
+ nExtra
;
2430 aSz
.Width() += 4*nExtra
; // a _little_ more ...
2432 int nOuterSpace
= ImplGetSVData()->maNWFData
.mnMenuFormatExtraBorder
;
2433 aSz
.Width() += 2*nOuterSpace
;
2434 aSz
.Height() += 2*nOuterSpace
;
2438 nTextPos
= (USHORT
)(2*nExtra
);
2439 aSz
.Height() = nFontHeight
+6;
2441 // get menubar height from native methods if supported
2442 if( pWindow
->IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
2444 ImplControlValue aVal
;
2445 Region aNativeBounds
;
2446 Region aNativeContent
;
2448 Region
aCtrlRegion( Rectangle( tmp
, Size( 100, 15 ) ) );
2449 if( pWindow
->GetNativeControlRegion( ControlType(CTRL_MENUBAR
),
2450 ControlPart(PART_ENTIRE_CONTROL
),
2452 ControlState(CTRL_STATE_ENABLED
),
2459 int nNativeHeight
= aNativeBounds
.GetBoundRect().GetHeight();
2460 if( nNativeHeight
> aSz
.Height() )
2461 aSz
.Height() = nNativeHeight
;
2465 // account for the size of the close button, which actually is a toolbox
2466 // due to NWF this is variable
2467 long nCloserHeight
= ((MenuBarWindow
*) pWindow
)->MinCloseButtonSize().Height();
2468 if( aSz
.Height() < nCloserHeight
)
2469 aSz
.Height() = nCloserHeight
;
2473 aSz
.Width() += pLogo
->aBitmap
.GetSizePixel().Width();
2478 static void ImplPaintCheckBackground( Window
* i_pWindow
, const Rectangle
& i_rRect
, bool i_bHighlight
)
2480 BOOL bNativeOk
= FALSE
;
2481 if( i_pWindow
->IsNativeControlSupported( CTRL_TOOLBAR
, PART_BUTTON
) )
2483 ImplControlValue aControlValue
;
2484 Region
aCtrlRegion( i_rRect
);
2485 ControlState nState
= CTRL_STATE_PRESSED
| CTRL_STATE_ENABLED
;
2487 aControlValue
.setTristateVal( BUTTONVALUE_ON
);
2489 bNativeOk
= i_pWindow
->DrawNativeControl( CTRL_TOOLBAR
, PART_BUTTON
,
2490 aCtrlRegion
, nState
, aControlValue
,
2496 const StyleSettings
& rSettings
= i_pWindow
->GetSettings().GetStyleSettings();
2497 Color
aColor( i_bHighlight
? rSettings
.GetMenuHighlightTextColor() : rSettings
.GetHighlightColor() );
2498 i_pWindow
->DrawSelectionBackground( i_rRect
, 0, i_bHighlight
, TRUE
, FALSE
, 2, NULL
, &aColor
);
2502 void Menu::ImplPaint( Window
* pWin
, USHORT nBorder
, long nStartY
, MenuItemData
* pThisItemOnly
, BOOL bHighlighted
, bool bLayout
) const
2504 // Fuer Symbole: nFontHeight x nFontHeight
2505 long nFontHeight
= pWin
->GetTextHeight();
2506 long nExtra
= nFontHeight
/4;
2508 long nCheckHeight
= 0, nRadioHeight
= 0, nMaxCheckWidth
= 0;
2509 ImplGetNativeCheckAndRadioSize( pWin
, nCheckHeight
, nRadioHeight
, nMaxCheckWidth
);
2511 DecorationView
aDecoView( pWin
);
2512 const StyleSettings
& rSettings
= pWin
->GetSettings().GetStyleSettings();
2514 Point aTopLeft
, aTmpPos
;
2517 aTopLeft
.X() = pLogo
->aBitmap
.GetSizePixel().Width();
2519 int nOuterSpace
= 0;
2522 nOuterSpace
= ImplGetSVData()->maNWFData
.mnMenuFormatExtraBorder
;
2523 aTopLeft
.X() += nOuterSpace
;
2524 aTopLeft
.Y() += nOuterSpace
;
2527 Size aOutSz
= pWin
->GetOutputSizePixel();
2528 USHORT nCount
= (USHORT
)pItemList
->Count();
2530 mpLayoutData
->m_aVisibleItemBoundRects
.clear();
2531 for ( USHORT n
= 0; n
< nCount
; n
++ )
2533 MenuItemData
* pData
= pItemList
->GetDataFromPos( n
);
2534 if ( ImplIsVisible( n
) && ( !pThisItemOnly
|| ( pData
== pThisItemOnly
) ) )
2536 if ( pThisItemOnly
&& bHighlighted
)
2537 pWin
->SetTextColor( rSettings
.GetMenuHighlightTextColor() );
2539 Point
aPos( aTopLeft
);
2540 aPos
.Y() += nBorder
;
2541 aPos
.Y() += nStartY
;
2543 if ( aPos
.Y() >= 0 )
2545 long nTextOffsetY
= ((pData
->aSz
.Height()-nFontHeight
)/2);
2547 nTextOffsetY
+= (aOutSz
.Height()-pData
->aSz
.Height()) / 2;
2548 USHORT nTextStyle
= 0;
2549 USHORT nSymbolStyle
= 0;
2550 USHORT nImageStyle
= 0;
2551 // SubMenus ohne Items werden nicht mehr disablte dargestellt,
2552 // wenn keine Items enthalten sind, da die Anwendung selber
2553 // darauf achten muss. Ansonsten gibt es Faelle, wo beim
2554 // asyncronen laden die Eintraege disablte dargestellt werden.
2555 if ( !pData
->bEnabled
)
2557 nTextStyle
|= TEXT_DRAW_DISABLE
;
2558 nSymbolStyle
|= SYMBOL_DRAW_DISABLE
;
2559 nImageStyle
|= IMAGE_DRAW_DISABLE
;
2563 if ( !bLayout
&& !bIsMenuBar
&& ( pData
->eType
== MENUITEM_SEPARATOR
) )
2565 aTmpPos
.Y() = aPos
.Y() + ((pData
->aSz
.Height()-2)/2);
2566 aTmpPos
.X() = aPos
.X() + 2 + nOuterSpace
;
2567 pWin
->SetLineColor( rSettings
.GetShadowColor() );
2568 pWin
->DrawLine( aTmpPos
, Point( aOutSz
.Width() - 3 - 2*nOuterSpace
, aTmpPos
.Y() ) );
2570 pWin
->SetLineColor( rSettings
.GetLightColor() );
2571 pWin
->DrawLine( aTmpPos
, Point( aOutSz
.Width() - 3 - 2*nOuterSpace
, aTmpPos
.Y() ) );
2572 pWin
->SetLineColor();
2575 Rectangle
aOuterCheckRect( Point( aPos
.X()+nCheckPos
, aPos
.Y() ), Size( pData
->aSz
.Height(), pData
->aSz
.Height() ) );
2576 aOuterCheckRect
.Left() += 1;
2577 aOuterCheckRect
.Right() -= 1;
2578 aOuterCheckRect
.Top() += 1;
2579 aOuterCheckRect
.Bottom() -= 1;
2582 if ( !bLayout
&& !bIsMenuBar
&& pData
->HasCheck() )
2584 // draw selection transparent marker if checked
2585 // onto that either a checkmark or the item image
2587 // however do not do this if native checks will be painted since
2588 // the selection color too often does not fit the theme's check and/or radio
2590 if( ! ( ( pData
->eType
== MENUITEM_IMAGE
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
) ) )
2592 if ( pWin
->IsNativeControlSupported( CTRL_MENU_POPUP
,
2593 (pData
->nBits
& MIB_RADIOCHECK
)
2594 ? PART_MENU_ITEM_CHECK_MARK
2595 : PART_MENU_ITEM_RADIO_MARK
) )
2597 ControlPart nPart
= ((pData
->nBits
& MIB_RADIOCHECK
)
2598 ? PART_MENU_ITEM_RADIO_MARK
2599 : PART_MENU_ITEM_CHECK_MARK
);
2601 ControlState nState
= 0;
2603 if ( pData
->bChecked
)
2604 nState
|= CTRL_STATE_PRESSED
;
2606 if ( pData
->bEnabled
)
2607 nState
|= CTRL_STATE_ENABLED
;
2610 nState
|= CTRL_STATE_SELECTED
;
2612 long nCtrlHeight
= (pData
->nBits
& MIB_RADIOCHECK
) ? nCheckHeight
: nRadioHeight
;
2613 aTmpPos
.X() = aOuterCheckRect
.Left() + (aOuterCheckRect
.GetWidth() - nCtrlHeight
)/2;
2614 aTmpPos
.Y() = aOuterCheckRect
.Top() + (aOuterCheckRect
.GetHeight() - nCtrlHeight
)/2;
2616 Rectangle
aCheckRect( aTmpPos
, Size( nCtrlHeight
, nCtrlHeight
) );
2617 pWin
->DrawNativeControl( CTRL_MENU_POPUP
, nPart
,
2618 Region( aCheckRect
),
2623 else if ( pData
->bChecked
) // by default do nothing for unchecked items
2625 ImplPaintCheckBackground( pWin
, aOuterCheckRect
, pThisItemOnly
&& bHighlighted
);
2629 if ( pData
->nBits
& MIB_RADIOCHECK
)
2631 eSymbol
= SYMBOL_RADIOCHECKMARK
;
2632 aSymbolSize
= Size( nFontHeight
/2, nFontHeight
/2 );
2636 eSymbol
= SYMBOL_CHECKMARK
;
2637 aSymbolSize
= Size( (nFontHeight
*25)/40, nFontHeight
/2 );
2639 aTmpPos
.X() = aOuterCheckRect
.Left() + (aOuterCheckRect
.GetWidth() - aSymbolSize
.Width())/2;
2640 aTmpPos
.Y() = aOuterCheckRect
.Top() + (aOuterCheckRect
.GetHeight() - aSymbolSize
.Height())/2;
2641 Rectangle
aRect( aTmpPos
, aSymbolSize
);
2642 aDecoView
.DrawSymbol( aRect
, eSymbol
, pWin
->GetTextColor(), nSymbolStyle
);
2648 if ( !bLayout
&& !bIsMenuBar
&& ( ( pData
->eType
== MENUITEM_IMAGE
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
) ) )
2650 // Don't render an image for a check thing
2651 if ((nMenuFlags
& MENU_FLAG_SHOWCHECKIMAGES
) || !pData
->HasCheck() )
2653 if( pData
->bChecked
)
2654 ImplPaintCheckBackground( pWin
, aOuterCheckRect
, pThisItemOnly
&& bHighlighted
);
2655 aTmpPos
= aOuterCheckRect
.TopLeft();
2656 aTmpPos
.X() += (aOuterCheckRect
.GetWidth()-pData
->aImage
.GetSizePixel().Width())/2;
2657 aTmpPos
.Y() += (aOuterCheckRect
.GetHeight()-pData
->aImage
.GetSizePixel().Height())/2;
2658 pWin
->DrawImage( aTmpPos
, pData
->aImage
, nImageStyle
);
2663 if ( ( pData
->eType
== MENUITEM_STRING
) || ( pData
->eType
== MENUITEM_STRINGIMAGE
) )
2665 aTmpPos
.X() = aPos
.X() + nTextPos
;
2666 aTmpPos
.Y() = aPos
.Y();
2667 aTmpPos
.Y() += nTextOffsetY
;
2668 USHORT nStyle
= nTextStyle
|TEXT_DRAW_MNEMONIC
;
2669 if ( pData
->bIsTemporary
)
2670 nStyle
|= TEXT_DRAW_DISABLE
;
2671 MetricVector
* pVector
= bLayout
? &mpLayoutData
->m_aUnicodeBoundRects
: NULL
;
2672 String
* pDisplayText
= bLayout
? &mpLayoutData
->m_aDisplayText
: NULL
;
2675 mpLayoutData
->m_aLineIndices
.push_back( mpLayoutData
->m_aDisplayText
.Len() );
2676 mpLayoutData
->m_aLineItemIds
.push_back( pData
->nId
);
2677 mpLayoutData
->m_aLineItemPositions
.push_back( n
);
2679 // #i47946# with NWF painted menus the background is transparent
2680 // since DrawCtrlText can depend on the background (e.g. for
2681 // TEXT_DRAW_DISABLE), temporarily set a background which
2682 // hopefully matches the NWF background since it is read
2683 // from the system style settings
2684 bool bSetTmpBackground
= !pWin
->IsBackground() && pWin
->IsNativeControlSupported( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
);
2685 if( bSetTmpBackground
)
2687 Color aBg
= bIsMenuBar
?
2688 pWin
->GetSettings().GetStyleSettings().GetMenuBarColor() :
2689 pWin
->GetSettings().GetStyleSettings().GetMenuColor();
2690 pWin
->SetBackground( Wallpaper( aBg
) );
2692 pWin
->DrawCtrlText( aTmpPos
, pData
->aText
, 0, pData
->aText
.Len(), nStyle
, pVector
, pDisplayText
);
2693 if( bSetTmpBackground
)
2694 pWin
->SetBackground();
2698 if ( !bLayout
&& !bIsMenuBar
&& pData
->aAccelKey
.GetCode() && !ImplAccelDisabled() )
2700 XubString aAccText
= pData
->aAccelKey
.GetName();
2701 aTmpPos
.X() = aOutSz
.Width() - pWin
->GetTextWidth( aAccText
);
2702 aTmpPos
.X() -= 4*nExtra
;
2704 aTmpPos
.X() -= nOuterSpace
;
2705 aTmpPos
.Y() = aPos
.Y();
2706 aTmpPos
.Y() += nTextOffsetY
;
2707 pWin
->DrawCtrlText( aTmpPos
, aAccText
, 0, aAccText
.Len(), nTextStyle
);
2711 if ( !bLayout
&& !bIsMenuBar
&& pData
->pSubMenu
)
2713 aTmpPos
.X() = aOutSz
.Width() - nFontHeight
+ nExtra
- nOuterSpace
;
2714 aTmpPos
.Y() = aPos
.Y();
2715 aTmpPos
.Y() += nExtra
/2;
2716 aTmpPos
.Y() += ( pData
->aSz
.Height() / 2 ) - ( nFontHeight
/4 );
2717 if ( pData
->nBits
& MIB_POPUPSELECT
)
2719 pWin
->SetTextColor( rSettings
.GetMenuTextColor() );
2720 Point
aTmpPos2( aPos
);
2721 aTmpPos2
.X() = aOutSz
.Width() - nFontHeight
- nFontHeight
/4;
2722 aDecoView
.DrawFrame(
2723 Rectangle( aTmpPos2
, Size( nFontHeight
+nFontHeight
/4, pData
->aSz
.Height() ) ), FRAME_DRAW_GROUP
);
2725 aDecoView
.DrawSymbol(
2726 Rectangle( aTmpPos
, Size( nFontHeight
/2, nFontHeight
/2 ) ),
2727 SYMBOL_SPIN_RIGHT
, pWin
->GetTextColor(), nSymbolStyle
);
2728 // if ( pData->nBits & MIB_POPUPSELECT )
2730 // aTmpPos.Y() += nFontHeight/2 ;
2731 // pWin->SetLineColor( rSettings.GetShadowColor() );
2732 // pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
2733 // pWin->SetLineColor( rSettings.GetLightColor() );
2735 // pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
2736 // pWin->SetLineColor();
2740 if ( pThisItemOnly
&& bHighlighted
)
2742 // This restores the normal menu or menu bar text
2743 // color for when it is no longer highlighted.
2745 pWin
->SetTextColor( rSettings
.GetMenuBarTextColor() );
2747 pWin
->SetTextColor( rSettings
.GetMenuTextColor() );
2753 mpLayoutData
->m_aVisibleItemBoundRects
[ n
] = Rectangle( aTopLeft
, Size( aOutSz
.Width(), pData
->aSz
.Height() ) );
2755 mpLayoutData
->m_aVisibleItemBoundRects
[ n
] = Rectangle( aTopLeft
, pData
->aSz
);
2761 aTopLeft
.Y() += pData
->aSz
.Height();
2765 aTopLeft
.X() += pData
->aSz
.Width();
2769 if ( !bLayout
&& !pThisItemOnly
&& pLogo
)
2771 Size aLogoSz
= pLogo
->aBitmap
.GetSizePixel();
2773 Rectangle
aRect( Point( 0, 0 ), Point( aLogoSz
.Width()-1, aOutSz
.Height() ) );
2774 if ( pWin
->GetColorCount() >= 256 )
2776 Gradient
aGrad( GRADIENT_LINEAR
, pLogo
->aStartColor
, pLogo
->aEndColor
);
2777 aGrad
.SetAngle( 1800 );
2778 aGrad
.SetBorder( 15 );
2779 pWin
->DrawGradient( aRect
, aGrad
);
2783 pWin
->SetFillColor( pLogo
->aStartColor
);
2784 pWin
->DrawRect( aRect
);
2787 Point
aLogoPos( 0, aOutSz
.Height() - aLogoSz
.Height() );
2788 pLogo
->aBitmap
.Draw( pWin
, aLogoPos
);
2792 Menu
* Menu::ImplGetStartMenu()
2794 Menu
* pStart
= this;
2795 while ( pStart
&& pStart
->pStartedFrom
&& ( pStart
->pStartedFrom
!= pStart
) )
2796 pStart
= pStart
->pStartedFrom
;
2800 void Menu::ImplCallHighlight( USHORT nHighlightedItem
)
2803 MenuItemData
* pData
= pItemList
->GetDataFromPos( nHighlightedItem
);
2805 nSelectedId
= pData
->nId
;
2806 ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT
, GetItemPos( GetCurItemId() ) );
2811 IMPL_LINK( Menu
, ImplCallSelect
, Menu
*, EMPTYARG
)
2818 Menu
* Menu::ImplFindSelectMenu()
2820 Menu
* pSelMenu
= nEventId
? this : NULL
;
2822 for ( ULONG n
= GetItemList()->Count(); n
&& !pSelMenu
; )
2824 MenuItemData
* pData
= GetItemList()->GetDataFromPos( --n
);
2826 if ( pData
->pSubMenu
)
2827 pSelMenu
= pData
->pSubMenu
->ImplFindSelectMenu();
2833 Menu
* Menu::ImplFindMenu( USHORT nItemId
)
2835 Menu
* pSelMenu
= NULL
;
2837 for ( ULONG n
= GetItemList()->Count(); n
&& !pSelMenu
; )
2839 MenuItemData
* pData
= GetItemList()->GetDataFromPos( --n
);
2841 if( pData
->nId
== nItemId
)
2843 else if ( pData
->pSubMenu
)
2844 pSelMenu
= pData
->pSubMenu
->ImplFindMenu( nItemId
);
2850 void Menu::RemoveDisabledEntries( BOOL bCheckPopups
, BOOL bRemoveEmptyPopups
)
2852 for ( USHORT n
= 0; n
< GetItemCount(); n
++ )
2854 BOOL bRemove
= FALSE
;
2855 MenuItemData
* pItem
= pItemList
->GetDataFromPos( n
);
2856 if ( pItem
->eType
== MENUITEM_SEPARATOR
)
2858 if ( !n
|| ( GetItemType( n
-1 ) == MENUITEM_SEPARATOR
) )
2862 bRemove
= !pItem
->bEnabled
;
2864 if ( bCheckPopups
&& pItem
->pSubMenu
)
2866 pItem
->pSubMenu
->RemoveDisabledEntries( TRUE
);
2867 if ( bRemoveEmptyPopups
&& !pItem
->pSubMenu
->GetItemCount() )
2875 if ( GetItemCount() )
2877 USHORT nLast
= GetItemCount() - 1;
2878 MenuItemData
* pItem
= pItemList
->GetDataFromPos( nLast
);
2879 if ( pItem
->eType
== MENUITEM_SEPARATOR
)
2880 RemoveItem( nLast
);
2882 delete mpLayoutData
, mpLayoutData
= NULL
;
2885 BOOL
Menu::HasValidEntries( BOOL bCheckPopups
)
2887 BOOL bValidEntries
= FALSE
;
2888 USHORT nCount
= GetItemCount();
2889 for ( USHORT n
= 0; !bValidEntries
&& ( n
< nCount
); n
++ )
2891 MenuItemData
* pItem
= pItemList
->GetDataFromPos( n
);
2892 if ( pItem
->bEnabled
&& ( pItem
->eType
!= MENUITEM_SEPARATOR
) )
2894 if ( bCheckPopups
&& pItem
->pSubMenu
)
2895 bValidEntries
= pItem
->pSubMenu
->HasValidEntries( TRUE
);
2897 bValidEntries
= TRUE
;
2900 return bValidEntries
;
2903 void Menu::SetLogo( const MenuLogo
& rLogo
)
2906 pLogo
= new MenuLogo( rLogo
);
2909 void Menu::SetLogo()
2915 MenuLogo
Menu::GetLogo() const
2923 void Menu::ImplKillLayoutData() const
2925 delete mpLayoutData
, mpLayoutData
= NULL
;
2928 void Menu::ImplFillLayoutData() const
2930 if( pWindow
&& pWindow
->IsReallyVisible() )
2932 mpLayoutData
= new MenuLayoutData();
2935 ImplPaint( pWindow
, 0, 0, 0, FALSE
, true );
2939 MenuFloatingWindow
* pFloat
= (MenuFloatingWindow
*)pWindow
;
2940 ImplPaint( pWindow
, pFloat
->nScrollerHeight
, pFloat
->ImplGetStartY(), 0, FALSE
, true );
2945 String
Menu::GetDisplayText() const
2947 if( ! mpLayoutData
)
2948 ImplFillLayoutData();
2949 return mpLayoutData
? mpLayoutData
->m_aDisplayText
: String();
2952 Rectangle
Menu::GetCharacterBounds( USHORT nItemID
, long nIndex
) const
2954 long nItemIndex
= -1;
2955 if( ! mpLayoutData
)
2956 ImplFillLayoutData();
2959 for( size_t i
= 0; i
< mpLayoutData
->m_aLineItemIds
.size(); i
++ )
2961 if( mpLayoutData
->m_aLineItemIds
[i
] == nItemID
)
2963 nItemIndex
= mpLayoutData
->m_aLineIndices
[i
];
2968 return (mpLayoutData
&& nItemIndex
!= -1) ? mpLayoutData
->GetCharacterBounds( nItemIndex
+nIndex
) : Rectangle();
2972 long Menu::GetIndexForPoint( const Point
& rPoint
, USHORT
& rItemID
) const
2976 if( ! mpLayoutData
)
2977 ImplFillLayoutData();
2980 nIndex
= mpLayoutData
->GetIndexForPoint( rPoint
);
2981 for( size_t i
= 0; i
< mpLayoutData
->m_aLineIndices
.size(); i
++ )
2983 if( mpLayoutData
->m_aLineIndices
[i
] <= nIndex
&&
2984 (i
== mpLayoutData
->m_aLineIndices
.size()-1 || mpLayoutData
->m_aLineIndices
[i
+1] > nIndex
) )
2986 // make index relative to item
2987 nIndex
-= mpLayoutData
->m_aLineIndices
[i
];
2988 rItemID
= mpLayoutData
->m_aLineItemIds
[i
];
2996 long Menu::GetLineCount() const
2998 if( ! mpLayoutData
)
2999 ImplFillLayoutData();
3000 return mpLayoutData
? mpLayoutData
->GetLineCount() : 0;
3003 Pair
Menu::GetLineStartEnd( long nLine
) const
3005 if( ! mpLayoutData
)
3006 ImplFillLayoutData();
3007 return mpLayoutData
? mpLayoutData
->GetLineStartEnd( nLine
) : Pair( -1, -1 );
3010 Pair
Menu::GetItemStartEnd( USHORT nItem
) const
3012 if( ! mpLayoutData
)
3013 ImplFillLayoutData();
3015 for( size_t i
= 0; i
< mpLayoutData
->m_aLineItemIds
.size(); i
++ )
3016 if( mpLayoutData
->m_aLineItemIds
[i
] == nItem
)
3017 return GetLineStartEnd( i
);
3019 return Pair( -1, -1 );
3022 USHORT
Menu::GetDisplayItemId( long nLine
) const
3025 if( ! mpLayoutData
)
3026 ImplFillLayoutData();
3027 if( mpLayoutData
&& ( nLine
>= 0 ) && ( nLine
< (long)mpLayoutData
->m_aLineItemIds
.size() ) )
3028 nItemId
= mpLayoutData
->m_aLineItemIds
[nLine
];
3032 BOOL
Menu::ConvertPoint( Point
& rPoint
, Window
* pReferenceWindow
) const
3035 if( pWindow
&& pReferenceWindow
)
3037 rPoint
= pReferenceWindow
->OutputToAbsoluteScreenPixel( rPoint
);
3038 rPoint
= pWindow
->AbsoluteScreenToOutputPixel( rPoint
);
3044 Rectangle
Menu::GetBoundingRectangle( USHORT nPos
) const
3048 if( ! mpLayoutData
)
3049 ImplFillLayoutData();
3052 std::map
< USHORT
, Rectangle
>::const_iterator it
= mpLayoutData
->m_aVisibleItemBoundRects
.find( nPos
);
3053 if( it
!= mpLayoutData
->m_aVisibleItemBoundRects
.end() )
3059 void Menu::SetAccessibleName( USHORT nItemId
, const XubString
& rStr
)
3062 MenuItemData
* pData
= pItemList
->GetData( nItemId
, nPos
);
3064 if ( pData
&& !rStr
.Equals( pData
->aAccessibleName
) )
3066 pData
->aAccessibleName
= rStr
;
3067 ImplCallEventListeners( VCLEVENT_MENU_ACCESSIBLENAMECHANGED
, nPos
);
3071 XubString
Menu::GetAccessibleName( USHORT nItemId
) const
3073 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
3076 return pData
->aAccessibleName
;
3078 return ImplGetSVEmptyStr();
3081 void Menu::SetAccessibleDescription( USHORT nItemId
, const XubString
& rStr
)
3083 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
3086 pData
->aAccessibleDescription
= rStr
;
3089 XubString
Menu::GetAccessibleDescription( USHORT nItemId
) const
3091 MenuItemData
* pData
= pItemList
->GetData( nItemId
);
3094 return pData
->aAccessibleDescription
;
3096 return ImplGetSVEmptyStr();
3099 void Menu::ImplSetSalMenu( SalMenu
*pSalMenu
)
3102 ImplGetSVData()->mpDefInst
->DestroyMenu( mpSalMenu
);
3103 mpSalMenu
= pSalMenu
;
3106 BOOL
Menu::GetSystemMenuData( SystemMenuData
* pData
) const
3108 Menu
* pMenu
= (Menu
*)this;
3109 if( pData
&& pMenu
->ImplGetSalMenu() )
3111 pMenu
->ImplGetSalMenu()->GetSystemMenuData( pData
);
3118 bool Menu::IsHighlighted( USHORT nItemPos
) const
3125 bRet
= ( nItemPos
== static_cast< MenuBarWindow
* > (pWindow
)->GetHighlightedItem() );
3127 bRet
= ( nItemPos
== static_cast< MenuFloatingWindow
* > (pWindow
)->GetHighlightedItem() );
3133 void Menu::HighlightItem( USHORT nItemPos
)
3139 MenuBarWindow
* pMenuWin
= static_cast< MenuBarWindow
* >( pWindow
);
3140 pMenuWin
->SetAutoPopup( FALSE
);
3141 pMenuWin
->ChangeHighlightItem( nItemPos
, FALSE
);
3145 static_cast< MenuFloatingWindow
* >( pWindow
)->ChangeHighlightItem( nItemPos
, FALSE
);
3154 MenuBar::MenuBar() : Menu( TRUE
)
3156 mbDisplayable
= TRUE
;
3157 mbCloserVisible
= FALSE
;
3158 mbFloatBtnVisible
= FALSE
;
3159 mbHideBtnVisible
= FALSE
;
3162 MenuBar::MenuBar( const MenuBar
& rMenu
) : Menu( TRUE
)
3164 mbDisplayable
= TRUE
;
3165 mbCloserVisible
= FALSE
;
3166 mbFloatBtnVisible
= FALSE
;
3167 mbHideBtnVisible
= FALSE
;
3172 MenuBar::MenuBar( const ResId
& rResId
) : Menu ( TRUE
)
3174 mbDisplayable
= TRUE
;
3175 mbCloserVisible
= FALSE
;
3176 mbFloatBtnVisible
= FALSE
;
3177 mbHideBtnVisible
= FALSE
;
3178 ImplLoadRes( rResId
);
3183 ImplDestroy( this, TRUE
);
3186 void MenuBar::ShowCloser( BOOL bShow
)
3188 ShowButtons( bShow
, mbFloatBtnVisible
, mbHideBtnVisible
);
3191 void MenuBar::ShowFloatButton( BOOL bShow
)
3193 ShowButtons( mbCloserVisible
, bShow
, mbHideBtnVisible
);
3196 void MenuBar::ShowHideButton( BOOL bShow
)
3198 ShowButtons( mbCloserVisible
, mbFloatBtnVisible
, bShow
);
3201 void MenuBar::ShowButtons( BOOL bClose
, BOOL bFloat
, BOOL bHide
)
3203 if ( (bClose
!= mbCloserVisible
) ||
3204 (bFloat
!= mbFloatBtnVisible
) ||
3205 (bHide
!= mbHideBtnVisible
) )
3207 mbCloserVisible
= bClose
;
3208 mbFloatBtnVisible
= bFloat
;
3209 mbHideBtnVisible
= bHide
;
3210 if ( ImplGetWindow() )
3211 ((MenuBarWindow
*)ImplGetWindow())->ShowButtons( bClose
, bFloat
, bHide
);
3215 void MenuBar::SetDisplayable( BOOL bDisplayable
)
3217 if( bDisplayable
!= mbDisplayable
)
3219 mbDisplayable
= bDisplayable
;
3220 MenuBarWindow
* pMenuWin
= (MenuBarWindow
*) ImplGetWindow();
3222 pMenuWin
->ImplLayoutChanged();
3226 Window
* MenuBar::ImplCreate( Window
* pParent
, Window
* pWindow
, MenuBar
* pMenu
)
3229 pWindow
= new MenuBarWindow( pParent
);
3231 pMenu
->pStartedFrom
= 0;
3232 pMenu
->pWindow
= pWindow
;
3233 ((MenuBarWindow
*)pWindow
)->SetMenu( pMenu
);
3234 long nHeight
= pMenu
->ImplCalcSize( pWindow
).Height();
3236 // depending on the native implementation or the displayable flag
3237 // the menubar windows is supressed (ie, height=0)
3238 if( !((MenuBar
*) pMenu
)->IsDisplayable() ||
3239 ( pMenu
->ImplGetSalMenu() && pMenu
->ImplGetSalMenu()->VisibleMenuBar() ) )
3242 pWindow
->SetPosSizePixel( 0, 0, 0, nHeight
, WINDOW_POSSIZE_HEIGHT
);
3246 void MenuBar::ImplDestroy( MenuBar
* pMenu
, BOOL bDelete
)
3248 MenuBarWindow
* pWindow
= (MenuBarWindow
*) pMenu
->ImplGetWindow();
3249 if ( pWindow
&& bDelete
)
3251 pWindow
->KillActivePopup();
3254 pMenu
->pWindow
= NULL
;
3257 BOOL
MenuBar::ImplHandleKeyEvent( const KeyEvent
& rKEvent
, BOOL bFromMenu
)
3261 // No keyboard processing when system handles the menu or our menubar is invisible
3262 if( !IsDisplayable() ||
3263 ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
3266 // Enabled-Abfragen, falls diese Methode von einem anderen Fenster gerufen wurde...
3267 Window
* pWin
= ImplGetWindow();
3268 if ( pWin
&& pWin
->IsEnabled() && pWin
->IsInputEnabled() && ! pWin
->IsInModalMode() )
3269 bDone
= ((MenuBarWindow
*)pWin
)->ImplHandleKeyEvent( rKEvent
, bFromMenu
);
3273 // -----------------------------------------------------------------------
3275 void MenuBar::SelectEntry( USHORT nId
)
3277 MenuBarWindow
* pMenuWin
= (MenuBarWindow
*) ImplGetWindow();
3281 pMenuWin
->GrabFocus();
3282 nId
= GetItemPos( nId
);
3284 // #99705# popup the selected menu
3285 pMenuWin
->SetAutoPopup( TRUE
);
3286 if( ITEMPOS_INVALID
!= pMenuWin
->nHighlightedItem
)
3288 pMenuWin
->KillActivePopup();
3289 pMenuWin
->ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
3291 if( nId
!= ITEMPOS_INVALID
)
3292 pMenuWin
->ChangeHighlightItem( nId
, FALSE
);
3296 // -----------------------------------------------------------------------
3298 // handler for native menu selection and command events
3300 BOOL
MenuBar::HandleMenuActivateEvent( Menu
*pMenu
) const
3304 pMenu
->pStartedFrom
= (Menu
*)this;
3305 pMenu
->bInCallback
= TRUE
;
3307 pMenu
->bInCallback
= FALSE
;
3312 BOOL
MenuBar::HandleMenuDeActivateEvent( Menu
*pMenu
) const
3316 pMenu
->pStartedFrom
= (Menu
*)this;
3317 pMenu
->bInCallback
= TRUE
;
3318 pMenu
->Deactivate();
3319 pMenu
->bInCallback
= FALSE
;
3324 BOOL
MenuBar::HandleMenuHighlightEvent( Menu
*pMenu
, USHORT nHighlightEventId
) const
3327 pMenu
= ((Menu
*) this)->ImplFindMenu( nHighlightEventId
);
3330 if( mnHighlightedItemPos
!= ITEMPOS_INVALID
)
3331 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT
, mnHighlightedItemPos
);
3333 pMenu
->mnHighlightedItemPos
= pMenu
->GetItemPos( nHighlightEventId
);
3334 pMenu
->nSelectedId
= nHighlightEventId
;
3335 pMenu
->pStartedFrom
= (Menu
*)this;
3336 pMenu
->ImplCallHighlight( pMenu
->mnHighlightedItemPos
);
3343 BOOL
MenuBar::HandleMenuCommandEvent( Menu
*pMenu
, USHORT nCommandEventId
) const
3346 pMenu
= ((Menu
*) this)->ImplFindMenu( nCommandEventId
);
3349 pMenu
->nSelectedId
= nCommandEventId
;
3350 pMenu
->pStartedFrom
= (Menu
*)this;
3351 pMenu
->ImplSelect();
3358 USHORT
MenuBar::AddMenuBarButton( const Image
& i_rImage
, const Link
& i_rLink
, USHORT i_nPos
)
3360 return AddMenuBarButton( i_rImage
, i_rLink
, String(), i_nPos
);
3363 USHORT
MenuBar::AddMenuBarButton( const Image
& i_rImage
, const Link
& i_rLink
, const String
& i_rToolTip
, USHORT i_nPos
)
3365 return pWindow
? static_cast<MenuBarWindow
*>(pWindow
)->AddMenuBarButton( i_rImage
, i_rLink
, i_rToolTip
, i_nPos
) : 0;
3368 void MenuBar::SetMenuBarButtonHighlightHdl( USHORT nId
, const Link
& rLink
)
3371 static_cast<MenuBarWindow
*>(pWindow
)->SetMenuBarButtonHighlightHdl( nId
, rLink
);
3374 Rectangle
MenuBar::GetMenuBarButtonRectPixel( USHORT nId
)
3376 return pWindow
? static_cast<MenuBarWindow
*>(pWindow
)->GetMenuBarButtonRectPixel( nId
) : Rectangle();
3379 void MenuBar::RemoveMenuBarButton( USHORT nId
)
3382 static_cast<MenuBarWindow
*>(pWindow
)->RemoveMenuBarButton( nId
);
3385 BOOL
MenuBar::HandleMenuButtonEvent( Menu
*, USHORT i_nButtonId
) const
3387 return static_cast<MenuBarWindow
*>(pWindow
)->HandleMenuButtonEvent( i_nButtonId
);
3390 // -----------------------------------------------------------------------
3392 // BOOL PopupMenu::bAnyPopupInExecute = FALSE;
3394 PopupMenu::PopupMenu()
3396 pRefAutoSubMenu
= NULL
;
3399 PopupMenu::PopupMenu( const ResId
& rResId
)
3401 pRefAutoSubMenu
= NULL
;
3402 ImplLoadRes( rResId
);
3405 PopupMenu::PopupMenu( const PopupMenu
& rMenu
) : Menu()
3407 pRefAutoSubMenu
= NULL
;
3411 PopupMenu::~PopupMenu()
3413 if( pRefAutoSubMenu
&& *pRefAutoSubMenu
== this )
3414 *pRefAutoSubMenu
= NULL
; // #111060# avoid second delete in ~MenuItemData
3417 BOOL
PopupMenu::IsInExecute()
3419 return GetActivePopupMenu() ? TRUE
: FALSE
;
3422 PopupMenu
* PopupMenu::GetActivePopupMenu()
3424 ImplSVData
* pSVData
= ImplGetSVData();
3425 return pSVData
->maAppData
.mpActivePopupMenu
;
3428 void PopupMenu::EndExecute( USHORT nSelectId
)
3430 if ( ImplGetWindow() )
3431 ImplGetFloatingWindow()->EndExecute( nSelectId
);
3434 void PopupMenu::SelectEntry( USHORT nId
)
3436 if ( ImplGetWindow() )
3438 if( nId
!= ITEMPOS_INVALID
)
3441 MenuItemData
* pData
= GetItemList()->GetData( nId
, nPos
);
3442 if ( pData
->pSubMenu
)
3443 ImplGetFloatingWindow()->ChangeHighlightItem( nPos
, TRUE
);
3445 ImplGetFloatingWindow()->EndExecute( nId
);
3449 MenuFloatingWindow
* pFloat
= ImplGetFloatingWindow();
3450 pFloat
->GrabFocus();
3452 for( nPos
= 0; nPos
< GetItemList()->Count(); nPos
++ )
3454 MenuItemData
* pData
= (MenuItemData
*)GetItemList()->GetObject( nPos
);
3455 if( pData
->pSubMenu
)
3457 pFloat
->KillActivePopup();
3460 pFloat
->ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
3465 void PopupMenu::SetSelectedEntry( USHORT nId
)
3470 USHORT
PopupMenu::Execute( Window
* pExecWindow
, const Point
& rPopupPos
)
3472 return Execute( pExecWindow
, Rectangle( rPopupPos
, rPopupPos
), POPUPMENU_EXECUTE_DOWN
);
3475 USHORT
PopupMenu::Execute( Window
* pExecWindow
, const Rectangle
& rRect
, USHORT nFlags
)
3477 ULONG nPopupModeFlags
= 0;
3478 if ( nFlags
& POPUPMENU_EXECUTE_DOWN
)
3479 nPopupModeFlags
= FLOATWIN_POPUPMODE_DOWN
;
3480 else if ( nFlags
& POPUPMENU_EXECUTE_UP
)
3481 nPopupModeFlags
= FLOATWIN_POPUPMODE_UP
;
3482 else if ( nFlags
& POPUPMENU_EXECUTE_LEFT
)
3483 nPopupModeFlags
= FLOATWIN_POPUPMODE_LEFT
;
3484 else if ( nFlags
& POPUPMENU_EXECUTE_RIGHT
)
3485 nPopupModeFlags
= FLOATWIN_POPUPMODE_RIGHT
;
3487 nPopupModeFlags
= FLOATWIN_POPUPMODE_DOWN
;
3489 if (nFlags
& POPUPMENU_NOMOUSEUPCLOSE
) // allow popup menus to stay open on mouse button up
3490 nPopupModeFlags
|= FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE
; // useful if the menu was opened on mousebutton down (eg toolbox configuration)
3492 return ImplExecute( pExecWindow
, rRect
, nPopupModeFlags
, 0, FALSE
);
3495 USHORT
PopupMenu::ImplExecute( Window
* pW
, const Rectangle
& rRect
, ULONG nPopupModeFlags
, Menu
* pSFrom
, BOOL bPreSelectFirst
)
3497 if ( !pSFrom
&& ( PopupMenu::IsInExecute() || !GetItemCount() ) )
3500 delete mpLayoutData
, mpLayoutData
= NULL
;
3502 ImplSVData
* pSVData
= ImplGetSVData();
3504 pStartedFrom
= pSFrom
;
3509 BOOL bRealExecute
= FALSE
;
3510 if ( !pStartedFrom
)
3512 pSVData
->maWinData
.mbNoDeactivate
= TRUE
;
3513 nFocusId
= Window::SaveFocus();
3514 bRealExecute
= TRUE
;
3518 // assure that only one menu is open at a time
3519 if( pStartedFrom
->bIsMenuBar
&& pSVData
->maWinData
.mpFirstFloat
)
3520 pSVData
->maWinData
.mpFirstFloat
->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL
| FLOATWIN_POPUPMODEEND_CLOSEALL
);
3523 DBG_ASSERT( !ImplGetWindow(), "Win?!" );
3524 Rectangle
aRect( rRect
);
3525 aRect
.SetPos( pW
->OutputToScreenPixel( aRect
.TopLeft() ) );
3527 WinBits nStyle
= WB_BORDER
;
3529 nPopupModeFlags
|= FLOATWIN_POPUPMODE_NEWLEVEL
;
3530 if ( !pStartedFrom
|| !pStartedFrom
->bIsMenuBar
)
3531 nPopupModeFlags
|= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK
| FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE
;
3533 nPopupModeFlags
|= FLOATWIN_POPUPMODE_NOKEYCLOSE
;
3535 // Kann beim Debuggen hilfreich sein.
3536 // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
3538 ImplDelData aDelData
;
3539 pW
->ImplAddDel( &aDelData
);
3541 bInCallback
= TRUE
; // hier schon setzen, falls Activate ueberladen
3543 bInCallback
= FALSE
;
3545 if ( aDelData
.IsDelete() )
3548 pW
->ImplRemoveDel( &aDelData
);
3550 if ( bCanceled
|| bKilled
)
3553 if ( !GetItemCount() )
3556 // Das Flag MENU_FLAG_HIDEDISABLEDENTRIES wird vererbt.
3559 if ( pSFrom
->nMenuFlags
& MENU_FLAG_HIDEDISABLEDENTRIES
)
3560 nMenuFlags
|= MENU_FLAG_HIDEDISABLEDENTRIES
;
3562 nMenuFlags
&= ~MENU_FLAG_HIDEDISABLEDENTRIES
;
3565 // #102790# context menues shall never show disabled entries
3566 nMenuFlags
|= MENU_FLAG_HIDEDISABLEDENTRIES
;
3569 USHORT nVisibleEntries
= ImplGetVisibleItemCount();
3570 if ( !nVisibleEntries
)
3572 ResMgr
* pResMgr
= ImplGetResMgr();
3575 String
aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE
, *pResMgr
) );
3576 MenuItemData
* pData
= pItemList
->Insert(
3577 0xFFFF, MENUITEM_STRING
, 0, aTmpEntryText
, Image(), NULL
, 0xFFFF );
3578 pData
->bIsTemporary
= TRUE
;
3581 else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags
& MENU_FLAG_NOAUTOMNEMONICS
) )
3583 CreateAutoMnemonics();
3586 MenuFloatingWindow
* pWin
= new MenuFloatingWindow( this, pW
, nStyle
| WB_SYSTEMWINDOW
);
3587 if( pSVData
->maNWFData
.mbFlatMenu
)
3588 pWin
->SetBorderStyle( WINDOW_BORDER_NOBORDER
);
3590 pWin
->SetBorderStyle( pWin
->GetBorderStyle() | WINDOW_BORDER_MENU
);
3593 Size aSz
= ImplCalcSize( pWin
);
3595 long nMaxHeight
= pWin
->GetDesktopRectPixel().GetHeight();
3596 if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
3598 Window
* pDeskW
= pWindow
->GetWindow( WINDOW_REALPARENT
);
3601 Point
aDesktopTL( pDeskW
->OutputToAbsoluteScreenPixel( aRect
.TopLeft() ) );
3602 nMaxHeight
= Application::GetWorkAreaPosSizePixel(
3603 Application::GetBestScreen( Rectangle( aDesktopTL
, aRect
.GetSize() ) )
3606 if ( pStartedFrom
&& pStartedFrom
->bIsMenuBar
)
3607 nMaxHeight
-= pW
->GetSizePixel().Height();
3608 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
3609 pWindow
->GetBorder( nLeft
, nTop
, nRight
, nBottom
);
3610 nMaxHeight
-= nTop
+nBottom
;
3611 if ( aSz
.Height() > nMaxHeight
)
3613 pWin
->EnableScrollMenu( TRUE
);
3614 USHORT nStart
= ImplGetFirstVisible();
3615 USHORT nEntries
= ImplCalcVisEntries( nMaxHeight
, nStart
);
3616 aSz
.Height() = ImplCalcHeight( nEntries
);
3619 pWin
->SetFocusId( nFocusId
);
3620 pWin
->SetOutputSizePixel( aSz
);
3621 // #102158# menus must never grab the focus, otherwise
3622 // they will be closed immediately
3623 // from now on focus grabbing is only prohibited automatically if
3624 // FLOATWIN_POPUPMODE_GRABFOCUS was set (which is done below), because some
3625 // floaters (like floating toolboxes) may grab the focus
3626 // pWin->GrabFocus();
3627 if ( GetItemCount() )
3629 SalMenu
* pMenu
= ImplGetSalMenu();
3630 if( pMenu
&& pMenu
->ShowNativePopupMenu( pWin
, aRect
, nPopupModeFlags
| FLOATWIN_POPUPMODE_GRABFOCUS
) )
3632 pWin
->StopExecute(0);
3634 pWindow
->doLazyDelete();
3640 pWin
->StartPopupMode( aRect
, nPopupModeFlags
| FLOATWIN_POPUPMODE_GRABFOCUS
);
3645 if( pSFrom
->bIsMenuBar
)
3646 aPos
= ((MenuBarWindow
*) pSFrom
->pWindow
)->GetHighlightedItem();
3648 aPos
= ((MenuFloatingWindow
*) pSFrom
->pWindow
)->GetHighlightedItem();
3650 pWin
->SetPosInParent( aPos
); // store position to be sent in SUBMENUDEACTIVATE
3651 pSFrom
->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE
, aPos
);
3654 if ( bPreSelectFirst
)
3656 USHORT nCount
= (USHORT
)pItemList
->Count();
3657 for ( USHORT n
= 0; n
< nCount
; n
++ )
3659 MenuItemData
* pData
= pItemList
->GetDataFromPos( n
);
3660 if ( ( pData
->bEnabled
|| !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus() )
3661 && ( pData
->eType
!= MENUITEM_SEPARATOR
) && ImplIsVisible( n
) && ImplIsSelectable( n
) )
3663 pWin
->ChangeHighlightItem( n
, FALSE
);
3670 pWin
->ImplAddDel( &aDelData
);
3672 ImplDelData aModalWinDel
;
3673 pW
->ImplAddDel( &aModalWinDel
);
3674 pW
->ImplIncModalCount();
3678 DBG_ASSERT( ! aModalWinDel
.IsDead(), "window for popup died, modal count incorrect !" );
3679 if( ! aModalWinDel
.IsDead() )
3680 pW
->ImplDecModalCount();
3682 if ( !aDelData
.IsDelete() )
3683 pWin
->ImplRemoveDel( &aDelData
);
3687 // Focus wieder herstellen (kann schon im Select wieder
3688 // hergestellt wurden sein
3689 nFocusId
= pWin
->GetFocusId();
3692 pWin
->SetFocusId( 0 );
3693 pSVData
->maWinData
.mbNoDeactivate
= FALSE
;
3695 pWin
->ImplEndPopupMode( 0, nFocusId
);
3697 if ( nSelectedId
) // Dann abraeumen... ( sonst macht TH das )
3699 PopupMenu
* pSub
= pWin
->GetActivePopup();
3702 pSub
->ImplGetFloatingWindow()->EndPopupMode();
3703 pSub
= pSub
->ImplGetFloatingWindow()->GetActivePopup();
3707 pWindow
->doLazyDelete();
3710 // Steht noch ein Select aus?
3711 Menu
* pSelect
= ImplFindSelectMenu();
3714 // Beim Popup-Menu muss das Select vor dem Verlassen von Execute gerufen werden!
3715 Application::RemoveUserEvent( pSelect
->nEventId
);
3716 pSelect
->nEventId
= 0;
3721 return bRealExecute
? nSelectedId
: 0;
3724 USHORT
PopupMenu::ImplCalcVisEntries( long nMaxHeight
, USHORT nStartEntry
, USHORT
* pLastVisible
) const
3726 nMaxHeight
-= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
3729 USHORT nEntries
= (USHORT
) pItemList
->Count();
3730 USHORT nVisEntries
= 0;
3735 for ( USHORT n
= nStartEntry
; n
< nEntries
; n
++ )
3737 if ( ImplIsVisible( n
) )
3739 MenuItemData
* pData
= pItemList
->GetDataFromPos( n
);
3740 nHeight
+= pData
->aSz
.Height();
3741 if ( nHeight
> nMaxHeight
)
3752 long PopupMenu::ImplCalcHeight( USHORT nEntries
) const
3757 for ( USHORT n
= 0; ( nFound
< nEntries
) && ( n
< pItemList
->Count() ); n
++ )
3759 if ( ImplIsVisible( (USHORT
) n
) )
3761 MenuItemData
* pData
= pItemList
->GetDataFromPos( n
);
3762 nHeight
+= pData
->aSz
.Height();
3767 nHeight
+= 2*ImplGetFloatingWindow()->GetScrollerHeight();
3773 static void ImplInitMenuWindow( Window
* pWin
, BOOL bFont
, BOOL bMenuBar
)
3775 const StyleSettings
& rStyleSettings
= pWin
->GetSettings().GetStyleSettings();
3778 pWin
->SetPointFont( rStyleSettings
.GetMenuFont() );
3781 if( pWin
->IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
3783 pWin
->SetBackground(); // background will be drawn by NWF
3787 Wallpaper aWallpaper
;
3788 aWallpaper
.SetStyle( WALLPAPER_APPLICATIONGRADIENT
);
3789 pWin
->SetBackground( aWallpaper
);
3790 pWin
->SetPaintTransparent( FALSE
);
3791 pWin
->SetParentClipMode( 0 );
3796 if( pWin
->IsNativeControlSupported( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
) )
3798 pWin
->SetBackground(); // background will be drawn by NWF
3801 pWin
->SetBackground( Wallpaper( rStyleSettings
.GetMenuColor() ) );
3805 pWin
->SetTextColor( rStyleSettings
.GetMenuBarTextColor() );
3807 pWin
->SetTextColor( rStyleSettings
.GetMenuTextColor() );
3808 pWin
->SetTextFillColor();
3809 pWin
->SetLineColor();
3812 MenuFloatingWindow::MenuFloatingWindow( Menu
* pMen
, Window
* pParent
, WinBits nStyle
) :
3813 FloatingWindow( pParent
, nStyle
)
3815 mpWindowImpl
->mbMenuFloatingWindow
= TRUE
;
3820 bScrollMenu
= FALSE
;
3821 nHighlightedItem
= ITEMPOS_INVALID
;
3822 nMBDownPos
= ITEMPOS_INVALID
;
3823 nPosInParent
= ITEMPOS_INVALID
;
3824 nScrollerHeight
= 0;
3826 nBorder
= EXTRASPACEY
;
3829 bScrollDown
= FALSE
;
3830 bIgnoreFirstMove
= TRUE
;
3833 EnableSaveBackground();
3834 ImplInitMenuWindow( this, TRUE
, FALSE
);
3836 SetPopupModeEndHdl( LINK( this, MenuFloatingWindow
, PopupEnd
) );
3838 aHighlightChangedTimer
.SetTimeoutHdl( LINK( this, MenuFloatingWindow
, HighlightChanged
) );
3839 aHighlightChangedTimer
.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3840 aSubmenuCloseTimer
.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3841 aSubmenuCloseTimer
.SetTimeoutHdl( LINK( this, MenuFloatingWindow
, SubmenuClose
) );
3842 aScrollTimer
.SetTimeoutHdl( LINK( this, MenuFloatingWindow
, AutoScroll
) );
3844 AddEventListener( LINK( this, MenuFloatingWindow
, ShowHideListener
) );
3847 void MenuFloatingWindow::doShutdown()
3851 // #105373# notify toolkit that highlight was removed
3852 // otherwise the entry will not be read when the menu is opened again
3853 if( nHighlightedItem
!= ITEMPOS_INVALID
)
3854 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT
, nHighlightedItem
);
3856 if( !bKeyInput
&& pMenu
&& pMenu
->pStartedFrom
&& !pMenu
->pStartedFrom
->bIsMenuBar
)
3858 // #102461# remove highlight in parent
3859 MenuItemData
* pData
;
3860 USHORT i
, nCount
= (USHORT
)pMenu
->pStartedFrom
->pItemList
->Count();
3861 for(i
= 0; i
< nCount
; i
++)
3863 pData
= pMenu
->pStartedFrom
->pItemList
->GetDataFromPos( i
);
3864 if( pData
&& ( pData
->pSubMenu
== pMenu
) )
3869 MenuFloatingWindow
* pPWin
= (MenuFloatingWindow
*)pMenu
->pStartedFrom
->ImplGetWindow();
3871 pPWin
->HighlightItem( i
, FALSE
);
3875 // free the reference to the accessible component
3876 SetAccessible( ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
>() );
3878 aHighlightChangedTimer
.Stop();
3880 // #95056# invalidate screen area covered by system window
3881 // so this can be taken into account if the commandhandler performs a scroll operation
3884 Rectangle
aInvRect( GetWindowExtentsRelative( GetParent() ) );
3885 GetParent()->Invalidate( aInvRect
);
3888 RemoveEventListener( LINK( this, MenuFloatingWindow
, ShowHideListener
) );
3892 MenuFloatingWindow::~MenuFloatingWindow()
3897 void MenuFloatingWindow::Resize()
3899 ImplInitClipRegion();
3902 long MenuFloatingWindow::ImplGetStartY() const
3907 for ( USHORT n
= 0; n
< nFirstEntry
; n
++ )
3908 nY
+= pMenu
->GetItemList()->GetDataFromPos( n
)->aSz
.Height();
3913 Region
MenuFloatingWindow::ImplCalcClipRegion( BOOL bIncludeLogo
) const
3915 Size aOutSz
= GetOutputSizePixel();
3917 Rectangle
aRect( aPos
, aOutSz
);
3918 aRect
.Top() += nScrollerHeight
;
3919 aRect
.Bottom() -= nScrollerHeight
;
3921 if ( pMenu
&& pMenu
->pLogo
&& !bIncludeLogo
)
3922 aRect
.Left() += pMenu
->pLogo
->aBitmap
.GetSizePixel().Width();
3924 Region aRegion
= aRect
;
3925 if ( pMenu
&& pMenu
->pLogo
&& bIncludeLogo
&& nScrollerHeight
)
3926 aRegion
.Union( Rectangle( Point(), Size( pMenu
->pLogo
->aBitmap
.GetSizePixel().Width(), aOutSz
.Height() ) ) );
3931 void MenuFloatingWindow::ImplInitClipRegion()
3933 if ( IsScrollMenu() )
3935 SetClipRegion( ImplCalcClipRegion() );
3943 void MenuFloatingWindow::ImplHighlightItem( const MouseEvent
& rMEvt
, BOOL bMBDown
)
3948 long nY
= nScrollerHeight
;
3949 long nMouseY
= rMEvt
.GetPosPixel().Y();
3950 Size aOutSz
= GetOutputSizePixel();
3951 if ( ( nMouseY
>= nY
) && ( nMouseY
< ( aOutSz
.Height() - nY
) ) )
3953 BOOL bHighlighted
= FALSE
;
3954 USHORT nCount
= (USHORT
)pMenu
->pItemList
->Count();
3955 nY
+= ImplGetStartY(); // ggf. gescrollt.
3956 for ( USHORT n
= 0; !bHighlighted
&& ( n
< nCount
); n
++ )
3958 if ( pMenu
->ImplIsVisible( n
) )
3960 MenuItemData
* pItemData
= pMenu
->pItemList
->GetDataFromPos( n
);
3962 nY
+= pItemData
->aSz
.Height();
3963 if ( ( nOldY
<= nMouseY
) && ( nY
> nMouseY
) && pMenu
->ImplIsSelectable( n
) )
3965 BOOL bPopupArea
= TRUE
;
3966 if ( pItemData
->nBits
& MIB_POPUPSELECT
)
3968 // Nur wenn ueber dem Pfeil geklickt wurde...
3969 Size aSz
= GetOutputSizePixel();
3970 long nFontHeight
= GetTextHeight();
3971 bPopupArea
= ( rMEvt
.GetPosPixel().X() >= ( aSz
.Width() - nFontHeight
- nFontHeight
/4 ) );
3976 if ( n
!= nHighlightedItem
)
3978 ChangeHighlightItem( (USHORT
)n
, FALSE
);
3981 BOOL bAllowNewPopup
= TRUE
;
3984 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
3985 bAllowNewPopup
= pData
&& ( pData
->pSubMenu
!= pActivePopup
);
3986 if ( bAllowNewPopup
)
3990 if ( bPopupArea
&& bAllowNewPopup
)
3992 HighlightChanged( NULL
);
3997 if ( n
!= nHighlightedItem
)
3999 ChangeHighlightItem( (USHORT
)n
, TRUE
);
4001 else if ( pItemData
->nBits
& MIB_POPUPSELECT
)
4003 if ( bPopupArea
&& ( pActivePopup
!= pItemData
->pSubMenu
) )
4004 HighlightChanged( NULL
);
4007 bHighlighted
= TRUE
;
4011 if ( !bHighlighted
)
4012 ChangeHighlightItem( ITEMPOS_INVALID
, TRUE
);
4016 ImplScroll( rMEvt
.GetPosPixel() );
4017 ChangeHighlightItem( ITEMPOS_INVALID
, TRUE
);
4021 IMPL_LINK( MenuFloatingWindow
, PopupEnd
, FloatingWindow
*, EMPTYARG
)
4023 // "this" will be deleted before the end of this method!
4029 //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
4030 KillActivePopup(); // should be ok to just remove it
4031 //pActivePopup->bCanceled = TRUE;
4034 pMenu
->bInCallback
= TRUE
;
4035 pMenu
->Deactivate();
4036 pMenu
->bInCallback
= FALSE
;
4042 // Wenn dies Fenster von TH geschlossen wurde, hat noch ein anderes
4043 // Menu dieses Fenster als pActivePopup.
4044 if ( pMenu
->pStartedFrom
)
4046 // Das pWin am 'Parent' kann aber schon 0 sein, falls die Kette von
4047 // vorne abgeraeumt wurde und jetzt die EndPopup-Events eintrudeln
4048 if ( pMenu
->pStartedFrom
->bIsMenuBar
)
4050 MenuBarWindow
* p
= (MenuBarWindow
*) pMenu
->pStartedFrom
->ImplGetWindow();
4052 p
->PopupClosed( pMenu
);
4056 MenuFloatingWindow
* p
= (MenuFloatingWindow
*) pMenu
->pStartedFrom
->ImplGetWindow();
4058 p
->KillActivePopup( (PopupMenu
*)pMenu
);
4065 pM
->pStartedFrom
= 0;
4070 IMPL_LINK( MenuFloatingWindow
, AutoScroll
, Timer
*, EMPTYARG
)
4072 ImplScroll( GetPointerPosPixel() );
4076 IMPL_LINK( MenuFloatingWindow
, HighlightChanged
, Timer
*, pTimer
)
4081 MenuItemData
* pItemData
= pMenu
->pItemList
->GetDataFromPos( nHighlightedItem
);
4084 if ( pActivePopup
&& ( pActivePopup
!= pItemData
->pSubMenu
) )
4086 ULONG nOldFlags
= GetPopupModeFlags();
4087 SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE
);
4089 SetPopupModeFlags( nOldFlags
);
4091 if ( pItemData
->bEnabled
&& pItemData
->pSubMenu
&& pItemData
->pSubMenu
->GetItemCount() && ( pItemData
->pSubMenu
!= pActivePopup
) )
4093 pActivePopup
= (PopupMenu
*)pItemData
->pSubMenu
;
4094 long nY
= nScrollerHeight
+ImplGetStartY();
4095 MenuItemData
* pData
= 0;
4096 for ( ULONG n
= 0; n
< nHighlightedItem
; n
++ )
4098 pData
= pMenu
->pItemList
->GetDataFromPos( n
);
4099 nY
+= pData
->aSz
.Height();
4101 pData
= pMenu
->pItemList
->GetDataFromPos( nHighlightedItem
);
4102 Size MySize
= GetOutputSizePixel();
4103 // Point MyPos = GetPosPixel();
4104 // Point aItemTopLeft( MyPos.X(), MyPos.Y()+nY );
4105 Point
aItemTopLeft( 0, nY
);
4106 Point
aItemBottomRight( aItemTopLeft
);
4107 aItemBottomRight
.X() += MySize
.Width();
4108 aItemBottomRight
.Y() += pData
->aSz
.Height();
4110 // Popups leicht versetzen:
4111 aItemTopLeft
.X() += 2;
4112 aItemBottomRight
.X() -= 2;
4113 if ( nHighlightedItem
)
4114 aItemTopLeft
.Y() -= 2;
4117 sal_Int32 nL
, nT
, nR
, nB
;
4118 GetBorder( nL
, nT
, nR
, nB
);
4119 aItemTopLeft
.Y() -= nT
;
4122 // pTest: Wegen Abstuerzen durch Reschedule() im Aufruf von Activate()
4123 // Ausserdem wird damit auch verhindert, dass SubMenus angezeigt werden,
4124 // die lange im Activate Rescheduled haben und jetzt schon nicht mehr
4125 // angezeigt werden sollen.
4126 Menu
* pTest
= pActivePopup
;
4127 ULONG nOldFlags
= GetPopupModeFlags();
4128 SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE
);
4129 USHORT nRet
= pActivePopup
->ImplExecute( this, Rectangle( aItemTopLeft
, aItemBottomRight
), FLOATWIN_POPUPMODE_RIGHT
, pMenu
, pTimer
? FALSE
: TRUE
);
4130 SetPopupModeFlags( nOldFlags
);
4132 // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
4133 if ( !nRet
&& ( pActivePopup
== pTest
) && pActivePopup
->ImplGetWindow() )
4134 pActivePopup
->ImplGetFloatingWindow()->AddPopupModeWindow( this );
4141 IMPL_LINK( MenuFloatingWindow
, SubmenuClose
, Timer
*, EMPTYARG
)
4143 if( pMenu
&& pMenu
->pStartedFrom
)
4145 MenuFloatingWindow
* pWin
= (MenuFloatingWindow
*) pMenu
->pStartedFrom
->GetWindow();
4147 pWin
->KillActivePopup();
4152 IMPL_LINK( MenuFloatingWindow
, ShowHideListener
, VclWindowEvent
*, pEvent
)
4157 if( pEvent
->GetId() == VCLEVENT_WINDOW_SHOW
)
4158 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_SHOW
, ITEMPOS_INVALID
);
4159 else if( pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
4160 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_HIDE
, ITEMPOS_INVALID
);
4164 void MenuFloatingWindow::EnableScrollMenu( BOOL b
)
4167 nScrollerHeight
= b
? (USHORT
) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
4169 ImplInitClipRegion();
4172 void MenuFloatingWindow::Execute()
4174 ImplSVData
* pSVData
= ImplGetSVData();
4176 pSVData
->maAppData
.mpActivePopupMenu
= (PopupMenu
*)pMenu
;
4179 // bCallingSelect = FALSE;
4181 while ( bInExecute
)
4182 Application::Yield();
4184 pSVData
->maAppData
.mpActivePopupMenu
= NULL
;
4186 // while ( bCallingSelect )
4187 // Application::Yield();
4190 void MenuFloatingWindow::StopExecute( ULONG nFocusId
)
4192 // Focus wieder herstellen
4193 // (kann schon im Select wieder hergestellt wurden sein)
4196 Window::EndSaveFocus( nFocusId
, FALSE
);
4197 nFocusId
= nSaveFocusId
;
4201 ImplGetSVData()->maWinData
.mbNoDeactivate
= FALSE
;
4204 ImplEndPopupMode( 0, nFocusId
);
4206 aHighlightChangedTimer
.Stop();
4212 // notify parent, needed for accessibility
4213 if( pMenu
&& pMenu
->pStartedFrom
)
4214 pMenu
->pStartedFrom
->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE
, nPosInParent
);
4217 void MenuFloatingWindow::KillActivePopup( PopupMenu
* pThisOnly
)
4219 if ( pActivePopup
&& ( !pThisOnly
|| ( pThisOnly
== pActivePopup
) ) )
4221 if( pActivePopup
->pWindow
!= NULL
)
4222 if( ((FloatingWindow
*) pActivePopup
->pWindow
)->IsInCleanUp() )
4223 return; // kill it later
4224 if ( pActivePopup
->bInCallback
)
4225 pActivePopup
->bCanceled
= TRUE
;
4227 // Vor allen Aktionen schon pActivePopup = 0, falls z.B.
4228 // PopupModeEndHdl des zu zerstoerenden Popups mal synchron gerufen wird.
4229 PopupMenu
* pPopup
= pActivePopup
;
4230 pActivePopup
= NULL
;
4231 pPopup
->bInCallback
= TRUE
;
4232 pPopup
->Deactivate();
4233 pPopup
->bInCallback
= FALSE
;
4234 if ( pPopup
->ImplGetWindow() )
4236 pPopup
->ImplGetFloatingWindow()->StopExecute();
4237 pPopup
->ImplGetFloatingWindow()->doShutdown();
4238 pPopup
->pWindow
->doLazyDelete();
4239 pPopup
->pWindow
= NULL
;
4246 void MenuFloatingWindow::EndExecute()
4248 Menu
* pStart
= pMenu
? pMenu
->ImplGetStartMenu() : NULL
;
4250 if ( pStart
&& pStart
->bIsMenuBar
)
4252 nFocusId
= ((MenuBarWindow
*)((MenuBar
*)pStart
)->ImplGetWindow())->GetFocusId();
4255 ((MenuBarWindow
*)((MenuBar
*)pStart
)->ImplGetWindow())->SetFocusId( 0 );
4256 ImplGetSVData()->maWinData
.mbNoDeactivate
= FALSE
;
4260 // Wenn von woanders gestartet, dann ab dort aufraumen:
4261 MenuFloatingWindow
* pCleanUpFrom
= this;
4262 MenuFloatingWindow
* pWin
= this;
4263 while ( pWin
&& !pWin
->bInExecute
&&
4264 pWin
->pMenu
->pStartedFrom
&& !pWin
->pMenu
->pStartedFrom
->bIsMenuBar
)
4266 pWin
= ((PopupMenu
*)pWin
->pMenu
->pStartedFrom
)->ImplGetFloatingWindow();
4269 pCleanUpFrom
= pWin
;
4271 // Dies Fenster wird gleich zerstoert => Daten lokal merken...
4273 USHORT nItem
= nHighlightedItem
;
4275 pCleanUpFrom
->StopExecute( nFocusId
);
4277 if ( nItem
!= ITEMPOS_INVALID
&& pM
)
4279 MenuItemData
* pItemData
= pM
->GetItemList()->GetDataFromPos( nItem
);
4280 if ( pItemData
&& !pItemData
->bIsTemporary
)
4282 pM
->nSelectedId
= pItemData
->nId
;
4284 pStart
->nSelectedId
= pItemData
->nId
;
4291 void MenuFloatingWindow::EndExecute( USHORT nId
)
4294 if ( pMenu
&& pMenu
->GetItemList()->GetData( nId
, nPos
) )
4295 nHighlightedItem
= nPos
;
4297 nHighlightedItem
= ITEMPOS_INVALID
;
4302 void MenuFloatingWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
4304 // TH macht ein ToTop auf dieses Fenster, aber das aktive Popup
4305 // soll oben bleiben...
4306 // due to focus chage this would close all menues -> don't do it (#94123)
4307 //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
4308 // pActivePopup->ImplGetFloatingWindow()->ToTop( TOTOP_NOGRABFOCUS );
4310 ImplHighlightItem( rMEvt
, TRUE
);
4312 nMBDownPos
= nHighlightedItem
;
4315 void MenuFloatingWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
4317 MenuItemData
* pData
= pMenu
? pMenu
->GetItemList()->GetDataFromPos( nHighlightedItem
) : NULL
;
4318 // nMBDownPos in lokaler Variable merken und gleich zuruecksetzen,
4319 // weil nach EndExecute zu spaet
4320 USHORT _nMBDownPos
= nMBDownPos
;
4321 nMBDownPos
= ITEMPOS_INVALID
;
4322 if ( pData
&& pData
->bEnabled
&& ( pData
->eType
!= MENUITEM_SEPARATOR
) )
4324 if ( !pData
->pSubMenu
)
4328 else if ( ( pData
->nBits
& MIB_POPUPSELECT
) && ( nHighlightedItem
== _nMBDownPos
) && ( rMEvt
.GetClicks() == 2 ) )
4330 // Nicht wenn ueber dem Pfeil geklickt wurde...
4331 Size aSz
= GetOutputSizePixel();
4332 long nFontHeight
= GetTextHeight();
4333 if ( rMEvt
.GetPosPixel().X() < ( aSz
.Width() - nFontHeight
- nFontHeight
/4 ) )
4340 void MenuFloatingWindow::MouseMove( const MouseEvent
& rMEvt
)
4342 if ( !IsVisible() || rMEvt
.IsSynthetic() || rMEvt
.IsEnterWindow() )
4345 if ( rMEvt
.IsLeaveWindow() )
4348 if ( ImplHilite(rMEvt
) )
4351 // #102461# do not remove highlight if a popup menu is open at this position
4352 MenuItemData
* pData
= pMenu
? pMenu
->pItemList
->GetDataFromPos( nHighlightedItem
) : NULL
;
4353 // close popup with some delayed if we leave somewhere else
4354 if( pActivePopup
&& pData
&& pData
->pSubMenu
!= pActivePopup
)
4355 pActivePopup
->ImplGetFloatingWindow()->aSubmenuCloseTimer
.Start();
4357 if( !pActivePopup
|| (pData
&& pData
->pSubMenu
!= pActivePopup
) )
4358 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
4363 if ( IsScrollMenu() )
4364 ImplScroll( rMEvt
.GetPosPixel() );
4368 if ( ImplHilite(rMEvt
) )
4371 aSubmenuCloseTimer
.Stop();
4372 if( bIgnoreFirstMove
)
4373 bIgnoreFirstMove
= FALSE
;
4375 ImplHighlightItem( rMEvt
, FALSE
);
4379 void MenuFloatingWindow::ImplScroll( BOOL bUp
)
4387 HighlightItem( nHighlightedItem
, FALSE
);
4389 pMenu
->ImplKillLayoutData();
4391 if ( bScrollUp
&& bUp
)
4393 nFirstEntry
= pMenu
->ImplGetPrevVisible( nFirstEntry
);
4394 DBG_ASSERT( nFirstEntry
!= ITEMPOS_INVALID
, "Scroll?!" );
4396 long nScrollEntryHeight
= pMenu
->GetItemList()->GetDataFromPos( nFirstEntry
)->aSz
.Height();
4398 // nStartY += nEntryHeight;
4403 ImplDrawScroller( FALSE
);
4406 if ( pMenu
->ImplGetPrevVisible( nFirstEntry
) == ITEMPOS_INVALID
)
4409 ImplDrawScroller( TRUE
);
4412 Scroll( 0, nScrollEntryHeight
, ImplCalcClipRegion( FALSE
).GetBoundRect(), SCROLL_CLIP
);
4414 else if ( bScrollDown
&& !bUp
)
4416 long nScrollEntryHeight
= pMenu
->GetItemList()->GetDataFromPos( nFirstEntry
)->aSz
.Height();
4418 nFirstEntry
= pMenu
->ImplGetNextVisible( nFirstEntry
);
4419 DBG_ASSERT( nFirstEntry
!= ITEMPOS_INVALID
, "Scroll?!" );
4425 ImplDrawScroller( TRUE
);
4428 long nHeight
= GetOutputSizePixel().Height();
4429 USHORT nLastVisible
;
4430 ((PopupMenu
*)pMenu
)->ImplCalcVisEntries( nHeight
, nFirstEntry
, &nLastVisible
);
4431 if ( pMenu
->ImplGetNextVisible( nLastVisible
) == ITEMPOS_INVALID
)
4433 bScrollDown
= FALSE
;
4434 ImplDrawScroller( FALSE
);
4437 // nStartY -= nEntryHeight;
4438 Scroll( 0, -nScrollEntryHeight
, ImplCalcClipRegion( FALSE
).GetBoundRect(), SCROLL_CLIP
);
4441 HighlightItem( nHighlightedItem
, TRUE
);
4444 void MenuFloatingWindow::ImplScroll( const Point
& rMousePos
)
4446 Size aOutSz
= GetOutputSizePixel();
4448 long nY
= nScrollerHeight
;
4449 long nMouseY
= rMousePos
.Y();
4452 if ( bScrollUp
&& ( nMouseY
< nY
) )
4455 nDelta
= nY
- nMouseY
;
4457 else if ( bScrollDown
&& ( nMouseY
> ( aOutSz
.Height() - nY
) ) )
4459 ImplScroll( FALSE
);
4460 nDelta
= nMouseY
- ( aOutSz
.Height() - nY
);
4465 aScrollTimer
.Stop(); // Falls durch MouseMove gescrollt.
4469 else if ( nDelta
< 5 )
4471 else if ( nDelta
< 8 )
4473 else if ( nDelta
< 12 )
4477 aScrollTimer
.SetTimeout( nTimeout
);
4478 aScrollTimer
.Start();
4481 void MenuFloatingWindow::ChangeHighlightItem( USHORT n
, BOOL bStartPopupTimer
)
4483 // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
4484 // #65750# Dann verzichten wir lieber auf den schmalen Streifen Hintergrundsicherung.
4485 // Sonst lassen sich die Menus schlecht bedienen.
4486 // MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
4487 // if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
4488 // KillActivePopup();
4490 aSubmenuCloseTimer
.Stop();
4494 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
4496 HighlightItem( nHighlightedItem
, FALSE
);
4497 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT
, nHighlightedItem
);
4500 nHighlightedItem
= (USHORT
)n
;
4501 DBG_ASSERT( pMenu
->ImplIsVisible( nHighlightedItem
) || nHighlightedItem
== ITEMPOS_INVALID
, "ChangeHighlightItem: Not visible!" );
4502 if( nHighlightedItem
!= ITEMPOS_INVALID
)
4504 if( pMenu
->pStartedFrom
&& !pMenu
->pStartedFrom
->bIsMenuBar
)
4506 // #102461# make sure parent entry is highlighted as well
4507 MenuItemData
* pData
;
4508 USHORT i
, nCount
= (USHORT
)pMenu
->pStartedFrom
->pItemList
->Count();
4509 for(i
= 0; i
< nCount
; i
++)
4511 pData
= pMenu
->pStartedFrom
->pItemList
->GetDataFromPos( i
);
4512 if( pData
&& ( pData
->pSubMenu
== pMenu
) )
4517 MenuFloatingWindow
* pPWin
= (MenuFloatingWindow
*)pMenu
->pStartedFrom
->ImplGetWindow();
4518 if( pPWin
&& pPWin
->nHighlightedItem
!= i
)
4520 pPWin
->HighlightItem( i
, TRUE
);
4521 pPWin
->nHighlightedItem
= i
;
4525 HighlightItem( nHighlightedItem
, TRUE
);
4526 pMenu
->ImplCallHighlight( nHighlightedItem
);
4529 pMenu
->nSelectedId
= 0;
4531 if ( bStartPopupTimer
)
4533 // #102438# Menu items are not selectable
4534 // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
4535 // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
4536 // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
4537 if ( GetSettings().GetMouseSettings().GetMenuDelay() )
4538 aHighlightChangedTimer
.Start();
4540 HighlightChanged( &aHighlightChangedTimer
);
4544 void MenuFloatingWindow::HighlightItem( USHORT nPos
, BOOL bHighlight
)
4549 Size aSz
= GetOutputSizePixel();
4550 long nStartY
= ImplGetStartY();
4551 long nY
= nScrollerHeight
+nStartY
;
4555 nX
= pMenu
->pLogo
->aBitmap
.GetSizePixel().Width();
4557 int nOuterSpace
= ImplGetSVData()->maNWFData
.mnMenuFormatExtraBorder
;
4560 USHORT nCount
= (USHORT
)pMenu
->pItemList
->Count();
4561 for ( USHORT n
= 0; n
< nCount
; n
++ )
4563 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
4566 DBG_ASSERT( pMenu
->ImplIsVisible( n
), "Highlight: Item not visible!" );
4567 if ( pData
->eType
!= MENUITEM_SEPARATOR
)
4569 BOOL bRestoreLineColor
= FALSE
;
4571 bool bDrawItemRect
= true;
4573 Rectangle
aItemRect( Point( nX
+nOuterSpace
, nY
), Size( aSz
.Width()-2*nOuterSpace
, pData
->aSz
.Height() ) );
4574 if ( pData
->nBits
& MIB_POPUPSELECT
)
4576 long nFontHeight
= GetTextHeight();
4577 aItemRect
.Right() -= nFontHeight
+ nFontHeight
/4;
4580 if( IsNativeControlSupported( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
) )
4582 Size
aPxSize( GetOutputSizePixel() );
4583 Push( PUSH_CLIPREGION
);
4584 IntersectClipRegion( Rectangle( Point( nX
, nY
), Size( aSz
.Width(), pData
->aSz
.Height() ) ) );
4585 Rectangle
aCtrlRect( Point( nX
, 0 ), Size( aPxSize
.Width()-nX
, aPxSize
.Height() ) );
4586 DrawNativeControl( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
,
4587 Region( aCtrlRect
),
4592 IsNativeControlSupported( CTRL_MENU_POPUP
, PART_MENU_ITEM
) )
4594 bDrawItemRect
= false;
4595 if( FALSE
== DrawNativeControl( CTRL_MENU_POPUP
, PART_MENU_ITEM
,
4596 Region( aItemRect
),
4597 CTRL_STATE_SELECTED
| ( pData
->bEnabled
? CTRL_STATE_ENABLED
: 0 ),
4601 bDrawItemRect
= bHighlight
;
4605 bDrawItemRect
= bHighlight
;
4612 if( pData
->bEnabled
)
4613 SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4617 oldLineColor
= GetLineColor();
4618 SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4619 bRestoreLineColor
= TRUE
;
4623 SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
4625 DrawRect( aItemRect
);
4627 pMenu
->ImplPaint( this, nScrollerHeight
, nStartY
, pData
, bHighlight
);
4628 if( bRestoreLineColor
)
4629 SetLineColor( oldLineColor
);
4634 nY
+= pData
->aSz
.Height();
4638 Rectangle
MenuFloatingWindow::ImplGetItemRect( USHORT nPos
)
4644 Size aSz
= GetOutputSizePixel();
4645 long nStartY
= ImplGetStartY();
4646 long nY
= nScrollerHeight
+nStartY
;
4650 nX
= pMenu
->pLogo
->aBitmap
.GetSizePixel().Width();
4652 USHORT nCount
= (USHORT
)pMenu
->pItemList
->Count();
4653 for ( USHORT n
= 0; n
< nCount
; n
++ )
4655 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
4658 DBG_ASSERT( pMenu
->ImplIsVisible( n
), "ImplGetItemRect: Item not visible!" );
4659 if ( pData
->eType
!= MENUITEM_SEPARATOR
)
4661 aRect
= Rectangle( Point( nX
, nY
), Size( aSz
.Width(), pData
->aSz
.Height() ) );
4662 if ( pData
->nBits
& MIB_POPUPSELECT
)
4664 long nFontHeight
= GetTextHeight();
4665 aRect
.Right() -= nFontHeight
+ nFontHeight
/4;
4670 nY
+= pData
->aSz
.Height();
4676 void MenuFloatingWindow::ImplCursorUpDown( BOOL bUp
, BOOL bHomeEnd
)
4681 const StyleSettings
& rSettings
= GetSettings().GetStyleSettings();
4683 USHORT n
= nHighlightedItem
;
4684 if ( n
== ITEMPOS_INVALID
)
4689 n
= pMenu
->GetItemCount()-1;
4696 // absolute positioning
4699 n
= pMenu
->GetItemCount();
4716 if ( !IsScrollMenu() || ( nHighlightedItem
== ITEMPOS_INVALID
) )
4717 n
= pMenu
->GetItemCount()-1;
4724 if ( n
>= pMenu
->GetItemCount() )
4726 if ( !IsScrollMenu() || ( nHighlightedItem
== ITEMPOS_INVALID
) )
4733 MenuItemData
* pData
= (MenuItemData
*)pMenu
->GetItemList()->GetDataFromPos( n
);
4734 if ( ( pData
->bEnabled
|| !rSettings
.GetSkipDisabledInMenus() )
4735 && ( pData
->eType
!= MENUITEM_SEPARATOR
) && pMenu
->ImplIsVisible( n
) && pMenu
->ImplIsSelectable( n
) )
4737 // Selektion noch im sichtbaren Bereich?
4738 if ( IsScrollMenu() )
4740 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
4742 while ( n
< nFirstEntry
)
4745 Size aOutSz
= GetOutputSizePixel();
4746 USHORT nLastVisible
;
4747 ((PopupMenu
*)pMenu
)->ImplCalcVisEntries( aOutSz
.Height(), nFirstEntry
, &nLastVisible
);
4748 while ( n
> nLastVisible
)
4750 ImplScroll( FALSE
);
4751 ((PopupMenu
*)pMenu
)->ImplCalcVisEntries( aOutSz
.Height(), nFirstEntry
, &nLastVisible
);
4754 ChangeHighlightItem( n
, FALSE
);
4757 } while ( n
!= nLoop
);
4760 void MenuFloatingWindow::KeyInput( const KeyEvent
& rKEvent
)
4762 ImplDelData aDelData
;
4763 ImplAddDel( &aDelData
);
4765 USHORT nCode
= rKEvent
.GetKeyCode().GetCode();
4772 ImplCursorUpDown( nCode
== KEY_UP
);
4778 ImplCursorUpDown( nCode
== KEY_END
, TRUE
);
4784 // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
4785 if( nCode
== KEY_F6
&& !rKEvent
.GetKeyCode().IsMod1() )
4789 if ( !pMenu
->pStartedFrom
)
4794 else if ( pMenu
->pStartedFrom
->bIsMenuBar
)
4797 ((MenuBarWindow
*)((MenuBar
*)pMenu
->pStartedFrom
)->ImplGetWindow())->KeyInput( rKEvent
);
4802 PopupMenu
* pPopupMenu
= (PopupMenu
*)pMenu
->pStartedFrom
;
4803 MenuFloatingWindow
* pFloat
= pPopupMenu
->ImplGetFloatingWindow();
4804 pFloat
->GrabFocus();
4805 pFloat
->KillActivePopup();
4806 pPopupMenu
->ImplCallHighlight(pFloat
->nHighlightedItem
);
4813 if ( pMenu
&& pMenu
->pStartedFrom
)
4816 if ( pMenu
->pStartedFrom
->bIsMenuBar
)
4819 ((MenuBarWindow
*)((MenuBar
*)pMenu
->pStartedFrom
)->ImplGetWindow())->KeyInput( rKEvent
);
4823 MenuFloatingWindow
* pFloat
= ((PopupMenu
*)pMenu
->pStartedFrom
)->ImplGetFloatingWindow();
4824 pFloat
->GrabFocus();
4825 pFloat
->KillActivePopup();
4835 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
4837 MenuItemData
* pData
= pMenu
->GetItemList()->GetDataFromPos( nHighlightedItem
);
4838 if ( pData
&& pData
->pSubMenu
)
4840 HighlightChanged( 0 );
4846 Menu
* pStart
= pMenu
->ImplGetStartMenu();
4847 if ( pStart
&& pStart
->bIsMenuBar
)
4850 pStart
->ImplGetWindow()->KeyInput( rKEvent
);
4860 MenuItemData
* pData
= pMenu
->GetItemList()->GetDataFromPos( nHighlightedItem
);
4861 if ( pData
&& pData
->bEnabled
)
4863 if ( pData
->pSubMenu
)
4864 HighlightChanged( 0 );
4877 Menu
* pStart
= pMenu
->ImplGetStartMenu();
4878 if ( pStart
&& pStart
->bIsMenuBar
)
4881 pStart
->ImplGetWindow()->KeyInput( rKEvent
);
4888 xub_Unicode nCharCode
= rKEvent
.GetCharCode();
4890 USHORT nDuplicates
= 0;
4891 MenuItemData
* pData
= (nCharCode
&& pMenu
) ? pMenu
->GetItemList()->SearchItem( nCharCode
, rKEvent
.GetKeyCode(), nPos
, nDuplicates
, nHighlightedItem
) : NULL
;
4894 if ( pData
->pSubMenu
|| nDuplicates
> 1 )
4896 ChangeHighlightItem( nPos
, FALSE
);
4897 HighlightChanged( 0 );
4901 nHighlightedItem
= nPos
;
4907 // Bei ungueltigen Tasten Beepen, aber nicht bei HELP und F-Tasten
4908 if ( !rKEvent
.GetKeyCode().IsMod2() && ( nCode
!= KEY_HELP
) && ( rKEvent
.GetKeyCode().GetGroup() != KEYGROUP_FKEYS
) )
4910 FloatingWindow::KeyInput( rKEvent
);
4914 // #105474# check if menu window was not destroyed
4915 if ( !aDelData
.IsDelete() )
4917 ImplRemoveDel( &aDelData
);
4922 void MenuFloatingWindow::Paint( const Rectangle
& )
4927 if( IsNativeControlSupported( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
) )
4930 long nX
= pMenu
->pLogo
? pMenu
->pLogo
->aBitmap
.GetSizePixel().Width() : 0;
4931 Size
aPxSize( GetOutputSizePixel() );
4932 aPxSize
.Width() -= nX
;
4933 DrawNativeControl( CTRL_MENU_POPUP
, PART_ENTIRE_CONTROL
,
4934 Region( Rectangle( Point( nX
, 0 ), aPxSize
) ),
4938 ImplInitClipRegion();
4940 if ( IsScrollMenu() )
4942 ImplDrawScroller( TRUE
);
4943 ImplDrawScroller( FALSE
);
4945 SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
4946 pMenu
->ImplPaint( this, nScrollerHeight
, ImplGetStartY() );
4947 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
4948 HighlightItem( nHighlightedItem
, TRUE
);
4951 void MenuFloatingWindow::ImplDrawScroller( BOOL bUp
)
4958 Size aOutSz
= GetOutputSizePixel();
4959 long nY
= bUp
? 0 : ( aOutSz
.Height() - nScrollerHeight
);
4960 long nX
= pMenu
->pLogo
? pMenu
->pLogo
->aBitmap
.GetSizePixel().Width() : 0;
4961 Rectangle
aRect( Point( nX
, nY
), Size( aOutSz
.Width()-nX
, nScrollerHeight
) );
4963 DecorationView
aDecoView( this );
4964 SymbolType eSymbol
= bUp
? SYMBOL_SPIN_UP
: SYMBOL_SPIN_DOWN
;
4967 if ( ( bUp
&& !bScrollUp
) || ( !bUp
&& !bScrollDown
) )
4968 nStyle
|= SYMBOL_DRAW_DISABLE
;
4970 aDecoView
.DrawSymbol( aRect
, eSymbol
, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle
);
4972 ImplInitClipRegion();
4975 void MenuFloatingWindow::RequestHelp( const HelpEvent
& rHEvt
)
4977 USHORT nId
= nHighlightedItem
;
4981 // #102618# Get item rect before destroying the window in EndExecute() call
4982 Rectangle
aHighlightRect( ImplGetItemRect( nHighlightedItem
) );
4984 if ( rHEvt
.GetMode() & (HELPMODE_CONTEXT
| HELPMODE_EXTENDED
) )
4986 nHighlightedItem
= ITEMPOS_INVALID
;
4991 if( !ImplHandleHelpEvent( pW
, pM
, nId
, rHEvt
, aHighlightRect
) )
4992 Window::RequestHelp( rHEvt
);
4995 void MenuFloatingWindow::StateChanged( StateChangedType nType
)
4997 FloatingWindow::StateChanged( nType
);
4999 if ( ( nType
== STATE_CHANGE_CONTROLFOREGROUND
) || ( nType
== STATE_CHANGE_CONTROLBACKGROUND
) )
5001 ImplInitMenuWindow( this, FALSE
, FALSE
);
5006 void MenuFloatingWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
5008 FloatingWindow::DataChanged( rDCEvt
);
5010 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
5011 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
5012 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
5013 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
5015 ImplInitMenuWindow( this, FALSE
, FALSE
);
5020 void MenuFloatingWindow::Command( const CommandEvent
& rCEvt
)
5022 if ( rCEvt
.GetCommand() == COMMAND_WHEEL
)
5024 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
5025 if( !pData
->GetModifier() && ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
) )
5027 // ImplCursorUpDown( pData->GetDelta() > 0L );
5028 ImplScroll( pData
->GetDelta() > 0L );
5029 MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
5034 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> MenuFloatingWindow::CreateAccessible()
5036 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> xAcc
;
5038 if ( pMenu
&& !pMenu
->pStartedFrom
)
5039 xAcc
= pMenu
->GetAccessible();
5044 MenuBarWindow::MenuBarWindow( Window
* pParent
) :
5045 Window( pParent
, 0 ),
5047 aFloatBtn( this, WB_NOPOINTERFOCUS
| WB_SMALLSTYLE
| WB_RECTSTYLE
),
5048 aHideBtn( this, WB_NOPOINTERFOCUS
| WB_SMALLSTYLE
| WB_RECTSTYLE
)
5050 SetType( WINDOW_MENUBARWINDOW
);
5052 pActivePopup
= NULL
;
5054 nHighlightedItem
= ITEMPOS_INVALID
;
5057 bIgnoreFirstMove
= TRUE
;
5058 bStayActive
= FALSE
;
5060 ResMgr
* pResMgr
= ImplGetResMgr();
5064 BitmapEx
aBitmap( ResId( SV_RESID_BITMAP_CLOSEDOC
, *pResMgr
) );
5065 BitmapEx
aBitmapHC( ResId( SV_RESID_BITMAP_CLOSEDOCHC
, *pResMgr
) );
5067 aCloser
.maImage
= Image( aBitmap
);
5068 aCloser
.maImageHC
= Image( aBitmapHC
);
5070 aCloser
.SetOutStyle( TOOLBOX_STYLE_FLAT
);
5071 aCloser
.SetBackground();
5072 aCloser
.SetPaintTransparent( TRUE
);
5073 aCloser
.SetParentClipMode( PARENTCLIPMODE_NOCLIP
);
5075 aCloser
.InsertItem( IID_DOCUMENTCLOSE
,
5076 GetSettings().GetStyleSettings().GetMenuBarColor().IsDark() ? aCloser
.maImageHC
: aCloser
.maImage
, 0 );
5077 aCloser
.SetSelectHdl( LINK( this, MenuBarWindow
, CloserHdl
) );
5078 aCloser
.AddEventListener( LINK( this, MenuBarWindow
, ToolboxEventHdl
) );
5079 aCloser
.SetQuickHelpText( IID_DOCUMENTCLOSE
, XubString( ResId( SV_HELPTEXT_CLOSEDOCUMENT
, *pResMgr
) ) );
5081 aFloatBtn
.SetClickHdl( LINK( this, MenuBarWindow
, FloatHdl
) );
5082 aFloatBtn
.SetSymbol( SYMBOL_FLOAT
);
5083 aFloatBtn
.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_RESTORE
, *pResMgr
) ) );
5085 aHideBtn
.SetClickHdl( LINK( this, MenuBarWindow
, HideHdl
) );
5086 aHideBtn
.SetSymbol( SYMBOL_HIDE
);
5087 aHideBtn
.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_MINIMIZE
, *pResMgr
) ) );
5090 ImplInitStyleSettings();
5092 AddEventListener( LINK( this, MenuBarWindow
, ShowHideListener
) );
5095 MenuBarWindow::~MenuBarWindow()
5097 aCloser
.RemoveEventListener( LINK( this, MenuBarWindow
, ToolboxEventHdl
) );
5098 RemoveEventListener( LINK( this, MenuBarWindow
, ShowHideListener
) );
5101 void MenuBarWindow::SetMenu( MenuBar
* pMen
)
5105 nHighlightedItem
= ITEMPOS_INVALID
;
5106 ImplInitMenuWindow( this, TRUE
, TRUE
);
5109 aCloser
.ShowItem( IID_DOCUMENTCLOSE
, pMen
->HasCloser() );
5110 aCloser
.Show( pMen
->HasCloser() || !m_aAddButtons
.empty() );
5111 aFloatBtn
.Show( pMen
->HasFloatButton() );
5112 aHideBtn
.Show( pMen
->HasHideButton() );
5116 // show and connect native menubar
5117 if( pMenu
&& pMenu
->ImplGetSalMenu() )
5119 if( pMenu
->ImplGetSalMenu()->VisibleMenuBar() )
5120 ImplGetFrame()->SetMenu( pMenu
->ImplGetSalMenu() );
5122 pMenu
->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
5126 void MenuBarWindow::ShowButtons( BOOL bClose
, BOOL bFloat
, BOOL bHide
)
5128 aCloser
.ShowItem( IID_DOCUMENTCLOSE
, bClose
);
5129 aCloser
.Show( bClose
|| ! m_aAddButtons
.empty() );
5130 aFloatBtn
.Show( bFloat
);
5131 aHideBtn
.Show( bHide
);
5135 Size
MenuBarWindow::MinCloseButtonSize()
5137 return aCloser
.getMinSize();
5140 IMPL_LINK( MenuBarWindow
, CloserHdl
, PushButton
*, EMPTYARG
)
5145 if( aCloser
.GetCurItemId() == IID_DOCUMENTCLOSE
)
5146 return ((MenuBar
*)pMenu
)->GetCloserHdl().Call( pMenu
);
5147 std::map
<USHORT
,AddButtonEntry
>::iterator it
= m_aAddButtons
.find( aCloser
.GetCurItemId() );
5148 if( it
!= m_aAddButtons
.end() )
5150 MenuBar::MenuBarButtonCallbackArg aArg
;
5151 aArg
.nId
= it
->first
;
5152 aArg
.bHighlight
= (aCloser
.GetHighlightItemId() == it
->first
);
5153 aArg
.pMenuBar
= dynamic_cast<MenuBar
*>(pMenu
);
5154 return it
->second
.m_aSelectLink
.Call( &aArg
);
5159 IMPL_LINK( MenuBarWindow
, ToolboxEventHdl
, VclWindowEvent
*, pEvent
)
5164 MenuBar::MenuBarButtonCallbackArg aArg
;
5166 aArg
.bHighlight
= (pEvent
->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT
);
5167 aArg
.pMenuBar
= dynamic_cast<MenuBar
*>(pMenu
);
5168 if( pEvent
->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT
)
5169 aArg
.nId
= aCloser
.GetHighlightItemId();
5170 else if( pEvent
->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHTOFF
)
5172 USHORT nPos
= static_cast< USHORT
>(reinterpret_cast<sal_IntPtr
>(pEvent
->GetData()));
5173 aArg
.nId
= aCloser
.GetItemId( nPos
);
5175 std::map
< USHORT
, AddButtonEntry
>::iterator it
= m_aAddButtons
.find( aArg
.nId
);
5176 if( it
!= m_aAddButtons
.end() )
5178 it
->second
.m_aHighlightLink
.Call( &aArg
);
5183 IMPL_LINK( MenuBarWindow
, ShowHideListener
, VclWindowEvent
*, pEvent
)
5188 if( pEvent
->GetId() == VCLEVENT_WINDOW_SHOW
)
5189 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_SHOW
, ITEMPOS_INVALID
);
5190 else if( pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
5191 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_HIDE
, ITEMPOS_INVALID
);
5195 IMPL_LINK( MenuBarWindow
, FloatHdl
, PushButton
*, EMPTYARG
)
5197 return pMenu
? ((MenuBar
*)pMenu
)->GetFloatButtonClickHdl().Call( pMenu
) : 0;
5200 IMPL_LINK( MenuBarWindow
, HideHdl
, PushButton
*, EMPTYARG
)
5202 return pMenu
? ((MenuBar
*)pMenu
)->GetHideButtonClickHdl().Call( pMenu
) : 0;
5205 void MenuBarWindow::ImplCreatePopup( BOOL bPreSelectFirst
)
5207 MenuItemData
* pItemData
= pMenu
? pMenu
->GetItemList()->GetDataFromPos( nHighlightedItem
) : NULL
;
5210 bIgnoreFirstMove
= TRUE
;
5211 if ( pActivePopup
&& ( pActivePopup
!= pItemData
->pSubMenu
) )
5215 if ( pItemData
->bEnabled
&& pItemData
->pSubMenu
&& ( nHighlightedItem
!= ITEMPOS_INVALID
) && ( pItemData
->pSubMenu
!= pActivePopup
) )
5217 pActivePopup
= (PopupMenu
*)pItemData
->pSubMenu
;
5219 MenuItemData
* pData
= 0;
5220 for ( ULONG n
= 0; n
< nHighlightedItem
; n
++ )
5222 pData
= pMenu
->GetItemList()->GetDataFromPos( n
);
5223 nX
+= pData
->aSz
.Width();
5225 pData
= pMenu
->pItemList
->GetDataFromPos( nHighlightedItem
);
5226 // Point MyPos = GetPosPixel();
5227 // Point aItemTopLeft( MyPos.X()+nX, MyPos.Y() );
5228 Point
aItemTopLeft( nX
, 0 );
5229 Point
aItemBottomRight( aItemTopLeft
);
5230 aItemBottomRight
.X() += pData
->aSz
.Width();
5232 // Im Vollbild-Modus hat die MenuBar ggf. die Hoehe 0:
5233 // Nicht immer einfach die Window-Hoehe nehmen, weil ItemHeight < WindowHeight.
5234 if ( GetSizePixel().Height() )
5236 // #107747# give menuitems the height of the menubar
5237 aItemBottomRight
.Y() += GetOutputSizePixel().Height()-1;
5240 // ImplExecute ist doch nicht modal...
5241 // #99071# do not grab the focus, otherwise it will be restored to the menubar
5242 // when the frame is reactivated later
5244 pActivePopup
->ImplExecute( this, Rectangle( aItemTopLeft
, aItemBottomRight
), FLOATWIN_POPUPMODE_DOWN
, pMenu
, bPreSelectFirst
);
5247 // Hat kein Window, wenn vorher abgebrochen oder keine Eintraege
5248 if ( pActivePopup
->ImplGetFloatingWindow() )
5249 pActivePopup
->ImplGetFloatingWindow()->AddPopupModeWindow( this );
5251 pActivePopup
= NULL
;
5258 void MenuBarWindow::KillActivePopup()
5262 if( pActivePopup
->pWindow
!= NULL
)
5263 if( ((FloatingWindow
*) pActivePopup
->pWindow
)->IsInCleanUp() )
5264 return; // kill it later
5266 if ( pActivePopup
->bInCallback
)
5267 pActivePopup
->bCanceled
= TRUE
;
5269 pActivePopup
->bInCallback
= TRUE
;
5270 pActivePopup
->Deactivate();
5271 pActivePopup
->bInCallback
= FALSE
;
5272 // Abfrage auf pActivePopup, falls im Deactivate abgeschossen...
5273 if ( pActivePopup
&& pActivePopup
->ImplGetWindow() )
5275 pActivePopup
->ImplGetFloatingWindow()->StopExecute();
5276 pActivePopup
->ImplGetFloatingWindow()->doShutdown();
5277 pActivePopup
->pWindow
->doLazyDelete();
5278 pActivePopup
->pWindow
= NULL
;
5284 void MenuBarWindow::PopupClosed( Menu
* pPopup
)
5286 if ( pPopup
== pActivePopup
)
5289 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus
, FALSE
);
5293 void MenuBarWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
5296 USHORT nEntry
= ImplFindEntry( rMEvt
.GetPosPixel() );
5297 if ( ( nEntry
!= ITEMPOS_INVALID
) && ( nEntry
!= nHighlightedItem
) )
5299 ChangeHighlightItem( nEntry
, FALSE
);
5304 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
5308 void MenuBarWindow::MouseButtonUp( const MouseEvent
& )
5312 void MenuBarWindow::MouseMove( const MouseEvent
& rMEvt
)
5314 // Im Move nur Highlighten, wenn schon eins gehighlightet.
5315 if ( rMEvt
.IsSynthetic() || rMEvt
.IsLeaveWindow() || rMEvt
.IsEnterWindow() || ( nHighlightedItem
== ITEMPOS_INVALID
) )
5318 if( bIgnoreFirstMove
)
5320 bIgnoreFirstMove
= FALSE
;
5324 USHORT nEntry
= ImplFindEntry( rMEvt
.GetPosPixel() );
5325 if ( ( nEntry
!= ITEMPOS_INVALID
)
5327 && ( ImplHilite(rMEvt
) )
5329 && ( nEntry
!= nHighlightedItem
) )
5330 ChangeHighlightItem( nEntry
, FALSE
);
5333 void MenuBarWindow::ChangeHighlightItem( USHORT n
, BOOL bSelectEntry
, BOOL bAllowRestoreFocus
, BOOL bDefaultToDocument
)
5338 // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
5339 MenuItemData
* pNextData
= pMenu
->pItemList
->GetDataFromPos( n
);
5340 if ( pActivePopup
&& pActivePopup
->ImplGetWindow() && ( !pNextData
|| ( pActivePopup
!= pNextData
->pSubMenu
) ) )
5341 KillActivePopup(); // pActivePopup ggf. ohne pWin, wenn in Activate() Rescheduled wurde
5343 // Activate am MenuBar immer nur einmal pro Vorgang...
5344 BOOL bJustActivated
= FALSE
;
5345 if ( ( nHighlightedItem
== ITEMPOS_INVALID
) && ( n
!= ITEMPOS_INVALID
) )
5347 ImplGetSVData()->maWinData
.mbNoDeactivate
= TRUE
;
5350 // #105406# avoid saving the focus when we already have the focus
5351 BOOL bNoSaveFocus
= (this == ImplGetSVData()->maWinData
.mpFocusWin
);
5355 if( !ImplGetSVData()->maWinData
.mbNoSaveFocus
)
5357 // we didn't clean up last time
5358 Window::EndSaveFocus( nSaveFocusId
, FALSE
); // clean up
5361 nSaveFocusId
= Window::SaveFocus(); // only save focus when initially activated
5364 ; // do nothing: we 're activated again from taskpanelist, focus was already saved
5370 nSaveFocusId
= Window::SaveFocus(); // only save focus when initially activated
5374 bStayActive
= FALSE
;
5375 pMenu
->bInCallback
= TRUE
; // hier schon setzen, falls Activate ueberladen
5377 pMenu
->bInCallback
= FALSE
;
5378 bJustActivated
= TRUE
;
5380 else if ( ( nHighlightedItem
!= ITEMPOS_INVALID
) && ( n
== ITEMPOS_INVALID
) )
5382 pMenu
->bInCallback
= TRUE
;
5383 pMenu
->Deactivate();
5384 pMenu
->bInCallback
= FALSE
;
5385 ImplGetSVData()->maWinData
.mbNoDeactivate
= FALSE
;
5386 if( !ImplGetSVData()->maWinData
.mbNoSaveFocus
)
5388 ULONG nTempFocusId
= nSaveFocusId
;
5390 Window::EndSaveFocus( nTempFocusId
, bAllowRestoreFocus
);
5391 // #105406# restore focus to document if we could not save focus before
5392 if( bDefaultToDocument
&& !nTempFocusId
&& bAllowRestoreFocus
)
5393 GrabFocusToDocument();
5397 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
5399 HighlightItem( nHighlightedItem
, FALSE
);
5400 pMenu
->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT
, nHighlightedItem
);
5403 nHighlightedItem
= (USHORT
)n
;
5404 DBG_ASSERT( ( nHighlightedItem
== ITEMPOS_INVALID
) || pMenu
->ImplIsVisible( nHighlightedItem
), "ChangeHighlightItem: Not visible!" );
5405 HighlightItem( nHighlightedItem
, TRUE
);
5406 pMenu
->ImplCallHighlight( nHighlightedItem
);
5409 ImplCreatePopup( bSelectEntry
);
5411 // #58935# #73659# Focus, wenn kein Popup drunter haengt...
5412 if ( bJustActivated
&& !pActivePopup
)
5416 void MenuBarWindow::HighlightItem( USHORT nPos
, BOOL bHighlight
)
5422 ULONG nCount
= pMenu
->pItemList
->Count();
5423 for ( ULONG n
= 0; n
< nCount
; n
++ )
5425 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
5428 if ( pData
->eType
!= MENUITEM_SEPARATOR
)
5430 // #107747# give menuitems the height of the menubar
5431 Rectangle aRect
= Rectangle( Point( nX
, 1 ), Size( pData
->aSz
.Width(), GetOutputSizePixel().Height()-2 ) );
5432 Push( PUSH_CLIPREGION
);
5433 IntersectClipRegion( aRect
);
5436 if( IsNativeControlSupported( CTRL_MENUBAR
, PART_MENU_ITEM
) &&
5437 IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
5439 // draw background (transparency)
5440 ImplControlValue aControlValue
;
5441 MenubarValue aMenubarValue
;
5442 aMenubarValue
.maTopDockingAreaHeight
= ImplGetTopDockingAreaHeight( this );
5443 aControlValue
.setOptionalVal( (void *)(&aMenubarValue
) );
5446 Region
aBgRegion( Rectangle( tmp
, GetOutputSizePixel() ) );
5447 DrawNativeControl( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
,
5452 ImplAddNWFSeparator( this, aMenubarValue
);
5454 // draw selected item
5455 DrawNativeControl( CTRL_MENUBAR
, PART_MENU_ITEM
,
5457 CTRL_STATE_ENABLED
| CTRL_STATE_SELECTED
,
5463 SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
5470 if( IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
5472 ImplControlValue aControlValue
;
5473 MenubarValue aMenubarValue
;
5474 aMenubarValue
.maTopDockingAreaHeight
= ImplGetTopDockingAreaHeight( this );
5475 aControlValue
.setOptionalVal( (void *)(&aMenubarValue
) );
5477 // use full window size to get proper gradient
5478 // but clip accordingly
5480 Rectangle
aCtrlRect( aPt
, GetOutputSizePixel() );
5481 Region
aCtrlRegion( aCtrlRect
);
5483 DrawNativeControl( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
, aCtrlRegion
, CTRL_STATE_ENABLED
, aControlValue
, rtl::OUString() );
5484 ImplAddNWFSeparator( this, aMenubarValue
);
5490 pMenu
->ImplPaint( this, 0, 0, pData
, bHighlight
);
5495 nX
+= pData
->aSz
.Width();
5499 Rectangle
MenuBarWindow::ImplGetItemRect( USHORT nPos
)
5505 ULONG nCount
= pMenu
->pItemList
->Count();
5506 for ( ULONG n
= 0; n
< nCount
; n
++ )
5508 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
5511 if ( pData
->eType
!= MENUITEM_SEPARATOR
)
5512 // #107747# give menuitems the height of the menubar
5513 aRect
= Rectangle( Point( nX
, 1 ), Size( pData
->aSz
.Width(), GetOutputSizePixel().Height()-2 ) );
5517 nX
+= pData
->aSz
.Width();
5523 void MenuBarWindow::KeyInput( const KeyEvent
& rKEvent
)
5525 if ( !ImplHandleKeyEvent( rKEvent
) )
5526 Window::KeyInput( rKEvent
);
5529 BOOL
MenuBarWindow::ImplHandleKeyEvent( const KeyEvent
& rKEvent
, BOOL bFromMenu
)
5534 if ( pMenu
->bInCallback
)
5535 return TRUE
; // schlucken
5538 USHORT nCode
= rKEvent
.GetKeyCode().GetCode();
5542 if( GetParent()->GetWindow( WINDOW_CLIENT
)->IsSystemWindow() )
5544 SystemWindow
*pSysWin
= (SystemWindow
*)GetParent()->GetWindow( WINDOW_CLIENT
);
5545 if( pSysWin
->GetTaskPaneList() )
5546 if( pSysWin
->GetTaskPaneList()->HandleKeyEvent( rKEvent
) )
5551 if ( nCode
== KEY_MENU
&& !rKEvent
.GetKeyCode().IsShift() ) // only F10, not Shift-F10
5553 mbAutoPopup
= ImplGetSVData()->maNWFData
.mbOpenMenuOnF10
;
5554 if ( nHighlightedItem
== ITEMPOS_INVALID
)
5556 ChangeHighlightItem( 0, FALSE
);
5561 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
5566 else if ( bFromMenu
)
5568 if ( ( nCode
== KEY_LEFT
) || ( nCode
== KEY_RIGHT
) ||
5569 ( nCode
== KEY_HOME
) || ( nCode
== KEY_END
) )
5571 USHORT n
= nHighlightedItem
;
5572 if ( n
== ITEMPOS_INVALID
)
5574 if ( nCode
== KEY_LEFT
)
5577 n
= pMenu
->GetItemCount()-1;
5582 if( nCode
== KEY_HOME
)
5583 { n
= (USHORT
)-1; nLoop
= n
+1; }
5584 if( nCode
== KEY_END
)
5585 { n
= pMenu
->GetItemCount(); nLoop
= n
-1; }
5589 if ( nCode
== KEY_LEFT
|| nCode
== KEY_END
)
5594 n
= pMenu
->GetItemCount()-1;
5596 if ( nCode
== KEY_RIGHT
|| nCode
== KEY_HOME
)
5599 if ( n
>= pMenu
->GetItemCount() )
5603 MenuItemData
* pData
= (MenuItemData
*)pMenu
->GetItemList()->GetDataFromPos( n
);
5604 if ( ( pData
->eType
!= MENUITEM_SEPARATOR
) && pMenu
->ImplIsVisible( n
) )
5606 ChangeHighlightItem( n
, TRUE
);
5609 } while ( n
!= nLoop
);
5612 else if ( nCode
== KEY_RETURN
)
5614 if( pActivePopup
) KillActivePopup();
5618 ImplCreatePopup( TRUE
);
5623 else if ( ( nCode
== KEY_UP
) || ( nCode
== KEY_DOWN
) )
5627 ImplCreatePopup( TRUE
);
5632 else if ( nCode
== KEY_ESCAPE
|| ( nCode
== KEY_F6
&& rKEvent
.GetKeyCode().IsMod1() ) )
5636 // bring focus to menu bar without any open popup
5637 mbAutoPopup
= FALSE
;
5638 USHORT n
= nHighlightedItem
;
5639 nHighlightedItem
= ITEMPOS_INVALID
;
5641 ChangeHighlightItem( n
, FALSE
);
5642 bStayActive
= FALSE
;
5647 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
);
5649 if( nCode
== KEY_F6
&& rKEvent
.GetKeyCode().IsMod1() )
5651 // put focus into document
5652 GrabFocusToDocument();
5659 if ( !bDone
&& ( bFromMenu
|| rKEvent
.GetKeyCode().IsMod2() ) )
5661 xub_Unicode nCharCode
= rKEvent
.GetCharCode();
5664 USHORT nEntry
, nDuplicates
;
5665 MenuItemData
* pData
= pMenu
->GetItemList()->SearchItem( nCharCode
, rKEvent
.GetKeyCode(), nEntry
, nDuplicates
, nHighlightedItem
);
5666 if ( pData
&& (nEntry
!= ITEMPOS_INVALID
) )
5669 ChangeHighlightItem( nEntry
, TRUE
);
5674 // Wegen Systemmenu und anderen System-HotKeys, nur
5675 // eigenstaendige Character-Kombinationen auswerten
5676 USHORT nKeyCode
= rKEvent
.GetKeyCode().GetCode();
5677 if ( ((nKeyCode
>= KEY_A
) && (nKeyCode
<= KEY_Z
)) )
5685 void MenuBarWindow::Paint( const Rectangle
& )
5690 // no VCL paint if native menus
5691 if( pMenu
->ImplGetSalMenu() && pMenu
->ImplGetSalMenu()->VisibleMenuBar() )
5693 ImplGetFrame()->DrawMenuBar();
5697 if( IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
5700 Region
aCtrlRegion( Rectangle( aPt
, GetOutputSizePixel() ) );
5702 ImplControlValue aControlValue
;
5703 MenubarValue aMenubarValue
;
5704 aMenubarValue
.maTopDockingAreaHeight
= ImplGetTopDockingAreaHeight( this );
5705 aControlValue
.setOptionalVal( (void *)(&aMenubarValue
) );
5707 DrawNativeControl( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
, aCtrlRegion
, CTRL_STATE_ENABLED
, aControlValue
, rtl::OUString() );
5708 ImplAddNWFSeparator( this, aMenubarValue
);
5710 SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
5711 pMenu
->ImplPaint( this, 0 );
5712 if ( nHighlightedItem
!= ITEMPOS_INVALID
)
5713 HighlightItem( nHighlightedItem
, TRUE
);
5715 // in high contrast mode draw a separating line on the lower edge
5716 if( ! IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) &&
5717 GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
5719 Push( PUSH_LINECOLOR
| PUSH_MAPMODE
);
5720 SetLineColor( Color( COL_WHITE
) );
5721 SetMapMode( MapMode( MAP_PIXEL
) );
5722 Size aSize
= GetSizePixel();
5723 DrawLine( Point( 0, aSize
.Height()-1 ), Point( aSize
.Width()-1, aSize
.Height()-1 ) );
5729 void MenuBarWindow::Resize()
5731 Size aOutSz
= GetOutputSizePixel();
5732 long n
= aOutSz
.Height()-4;
5733 long nX
= aOutSz
.Width()-3;
5736 if ( aCloser
.IsVisible() )
5739 aCloser
.SetImages( n
);
5740 Size
aTbxSize( aCloser
.CalcWindowSizePixel() );
5741 nX
-= aTbxSize
.Width();
5742 long nTbxY
= (aOutSz
.Height() - aTbxSize
.Height())/2;
5743 aCloser
.SetPosSizePixel( nX
, nTbxY
, aTbxSize
.Width(), aTbxSize
.Height() );
5747 if ( aFloatBtn
.IsVisible() )
5750 aFloatBtn
.SetPosSizePixel( nX
, nY
, n
, n
);
5752 if ( aHideBtn
.IsVisible() )
5755 aHideBtn
.SetPosSizePixel( nX
, nY
, n
, n
);
5758 aFloatBtn
.SetSymbol( SYMBOL_FLOAT
);
5759 aHideBtn
.SetSymbol( SYMBOL_HIDE
);
5760 //aCloser.SetSymbol( SYMBOL_CLOSE ); //is a toolbox now
5765 USHORT
MenuBarWindow::ImplFindEntry( const Point
& rMousePos
) const
5770 USHORT nCount
= (USHORT
)pMenu
->pItemList
->Count();
5771 for ( USHORT n
= 0; n
< nCount
; n
++ )
5773 MenuItemData
* pData
= pMenu
->pItemList
->GetDataFromPos( n
);
5774 if ( pMenu
->ImplIsVisible( n
) )
5776 nX
+= pData
->aSz
.Width();
5777 if ( nX
> rMousePos
.X() )
5782 return ITEMPOS_INVALID
;
5785 void MenuBarWindow::RequestHelp( const HelpEvent
& rHEvt
)
5787 USHORT nId
= nHighlightedItem
;
5788 if ( rHEvt
.GetMode() & (HELPMODE_CONTEXT
| HELPMODE_EXTENDED
) )
5789 ChangeHighlightItem( ITEMPOS_INVALID
, TRUE
);
5791 Rectangle
aHighlightRect( ImplGetItemRect( nHighlightedItem
) );
5792 if( !ImplHandleHelpEvent( this, pMenu
, nId
, rHEvt
, aHighlightRect
) )
5793 Window::RequestHelp( rHEvt
);
5796 void MenuBarWindow::StateChanged( StateChangedType nType
)
5798 Window::StateChanged( nType
);
5800 if ( ( nType
== STATE_CHANGE_CONTROLFOREGROUND
) ||
5801 ( nType
== STATE_CHANGE_CONTROLBACKGROUND
) )
5803 ImplInitMenuWindow( this, FALSE
, TRUE
);
5807 pMenu
->ImplKillLayoutData();
5811 void MenuBarWindow::ImplLayoutChanged()
5815 ImplInitMenuWindow( this, TRUE
, TRUE
);
5816 // Falls sich der Font geaendert hat.
5817 long nHeight
= pMenu
->ImplCalcSize( this ).Height();
5819 // depending on the native implementation or the displayable flag
5820 // the menubar windows is supressed (ie, height=0)
5821 if( !((MenuBar
*) pMenu
)->IsDisplayable() ||
5822 ( pMenu
->ImplGetSalMenu() && pMenu
->ImplGetSalMenu()->VisibleMenuBar() ) )
5825 SetPosSizePixel( 0, 0, 0, nHeight
, WINDOW_POSSIZE_HEIGHT
);
5826 GetParent()->Resize();
5830 pMenu
->ImplKillLayoutData();
5834 void MenuBarWindow::ImplInitStyleSettings()
5836 if( IsNativeControlSupported( CTRL_MENUBAR
, PART_MENU_ITEM
) &&
5837 IsNativeControlSupported( CTRL_MENUBAR
, PART_ENTIRE_CONTROL
) )
5839 Color aHighlightTextColor
= ImplGetSVData()->maNWFData
.maMenuBarHighlightTextColor
;
5840 if( aHighlightTextColor
!= Color( COL_TRANSPARENT
) )
5842 AllSettings
aSettings( GetSettings() );
5843 StyleSettings
aStyle( aSettings
.GetStyleSettings() );
5844 aStyle
.SetMenuHighlightTextColor( aHighlightTextColor
);
5845 aSettings
.SetStyleSettings( aStyle
);
5846 OutputDevice::SetSettings( aSettings
);
5851 void MenuBarWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
5853 Window::DataChanged( rDCEvt
);
5855 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
5856 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
5857 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
5858 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
5860 ImplLayoutChanged();
5861 ImplInitStyleSettings();
5865 void MenuBarWindow::LoseFocus()
5867 if ( !HasChildPathFocus( TRUE
) )
5868 ChangeHighlightItem( ITEMPOS_INVALID
, FALSE
, FALSE
);
5871 void MenuBarWindow::GetFocus()
5873 if ( nHighlightedItem
== ITEMPOS_INVALID
)
5875 mbAutoPopup
= FALSE
; // do not open menu when activated by focus handling like taskpane cycling
5876 ChangeHighlightItem( 0, FALSE
);
5880 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> MenuBarWindow::CreateAccessible()
5882 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> xAcc
;
5885 xAcc
= pMenu
->GetAccessible();
5890 USHORT
MenuBarWindow::AddMenuBarButton( const Image
& i_rImage
, const Link
& i_rLink
, const String
& i_rToolTip
, USHORT i_nPos
)
5892 // find first free button id
5893 USHORT nId
= IID_DOCUMENTCLOSE
;
5894 std::map
< USHORT
, AddButtonEntry
>::const_iterator it
;
5895 if( i_nPos
> m_aAddButtons
.size() )
5896 i_nPos
= static_cast<USHORT
>(m_aAddButtons
.size());
5900 it
= m_aAddButtons
.find( nId
);
5901 } while( it
!= m_aAddButtons
.end() && nId
< 128 );
5902 DBG_ASSERT( nId
< 128, "too many addbuttons in menubar" );
5903 AddButtonEntry
& rNewEntry
= m_aAddButtons
[nId
];
5904 rNewEntry
.m_nId
= nId
;
5905 rNewEntry
.m_aSelectLink
= i_rLink
;
5906 aCloser
.InsertItem( nId
, i_rImage
, 0, 0 );
5907 aCloser
.calcMinSize();
5908 ShowButtons( aCloser
.IsItemVisible( IID_DOCUMENTCLOSE
),
5909 aFloatBtn
.IsVisible(),
5910 aHideBtn
.IsVisible() );
5911 ImplLayoutChanged();
5913 if( pMenu
->mpSalMenu
)
5914 pMenu
->mpSalMenu
->AddMenuBarButton( SalMenuButtonItem( nId
, i_rImage
, i_rToolTip
) );
5919 void MenuBarWindow::SetMenuBarButtonHighlightHdl( USHORT nId
, const Link
& rLink
)
5921 std::map
< USHORT
, AddButtonEntry
>::iterator it
= m_aAddButtons
.find( nId
);
5922 if( it
!= m_aAddButtons
.end() )
5923 it
->second
.m_aHighlightLink
= rLink
;
5926 Rectangle
MenuBarWindow::GetMenuBarButtonRectPixel( USHORT nId
)
5929 if( m_aAddButtons
.find( nId
) != m_aAddButtons
.end() )
5931 if( pMenu
->mpSalMenu
)
5933 aRect
= pMenu
->mpSalMenu
->GetMenuBarButtonRectPixel( nId
, ImplGetWindowImpl()->mpFrame
);
5934 if( aRect
== Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
5936 // system menu button is somehwere but location cannot be determined
5941 if( aRect
.IsEmpty() )
5943 aRect
= aCloser
.GetItemRect( nId
);
5944 Point aOffset
= aCloser
.OutputToScreenPixel( Point() );
5945 aRect
.Move( aOffset
.X(), aOffset
.Y() );
5951 void MenuBarWindow::RemoveMenuBarButton( USHORT nId
)
5953 USHORT nPos
= aCloser
.GetItemPos( nId
);
5954 aCloser
.RemoveItem( nPos
);
5955 m_aAddButtons
.erase( nId
);
5956 aCloser
.calcMinSize();
5957 ImplLayoutChanged();
5959 if( pMenu
->mpSalMenu
)
5960 pMenu
->mpSalMenu
->RemoveMenuBarButton( nId
);
5963 bool MenuBarWindow::HandleMenuButtonEvent( USHORT i_nButtonId
)
5965 std::map
< USHORT
, AddButtonEntry
>::iterator it
= m_aAddButtons
.find( i_nButtonId
);
5966 if( it
!= m_aAddButtons
.end() )
5968 MenuBar::MenuBarButtonCallbackArg aArg
;
5969 aArg
.nId
= it
->first
;
5970 aArg
.bHighlight
= true;
5971 aArg
.pMenuBar
= dynamic_cast<MenuBar
*>(pMenu
);
5972 return it
->second
.m_aSelectLink
.Call( &aArg
);