1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_VCL_MENU_HXX
21 #define INCLUDED_VCL_MENU_HXX
23 #include <rsc/rsc-vcl-shared-types.hxx>
24 #include <tools/color.hxx>
25 #include <tools/rc.hxx>
26 #include <tools/resid.hxx>
27 #include <tools/solar.h>
28 #include <vcl/dllapi.h>
29 #include <vcl/bitmapex.hxx>
30 #include <vcl/keycod.hxx>
31 #include <vcl/vclevent.hxx>
32 #include <com/sun/star/frame/XFrame.hpp>
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <o3tl/typed_flags_set.hxx>
47 class MenuFloatingWindow
;
48 namespace vcl
{ class Window
; }
51 struct SystemMenuData
;
52 enum class FloatWinPopupFlags
;
54 namespace com
{ namespace sun
{ namespace star
{ namespace accessibility
{
58 namespace vcl
{ struct MenuLayoutData
; }
60 #define MENU_APPEND (sal_uInt16(0xFFFF))
61 #define MENU_ITEM_NOTFOUND (sal_uInt16(0xFFFF))
63 // Must match the definitions in css::awt::PopupMenuDirection.idl
64 enum class PopupMenuFlags
70 ExecuteRight
= 0x0008,
71 NoMouseUpClose
= 0x0010,
72 //If there isn't enough space to put the menu where it wants
73 //to go, then they will be autoplaced. Toggle this bit
74 //on to force menus to be placed either above or below
75 //the starting rectangle and shrunk to fit and then scroll rather than place
76 //the menu beside that rectangle
77 NoHorzPlacement
= 0x0020,
82 template<> struct typed_flags
<PopupMenuFlags
> : is_typed_flags
<PopupMenuFlags
, 0x003f> {};
88 NoAutoMnemonics
= 0x0001,
89 HideDisabledEntries
= 0x0002,
90 // overrides default hiding of disabled entries in popup menus
91 AlwaysShowDisabledEntries
= 0x0004,
96 template<> struct typed_flags
<MenuFlags
> : is_typed_flags
<MenuFlags
, 0x0007> {};
99 /// Invalid menu item id
100 #define ITEMPOS_INVALID 0xFFFF
102 struct ImplMenuDelData
104 ImplMenuDelData
* mpNext
;
107 explicit ImplMenuDelData( const Menu
* );
110 bool isDeleted() const { return mpMenu
== 0; }
120 typedef void (*MenuUserDataReleaseFunction
)(sal_uLong
);
122 class VCL_DLLPUBLIC Menu
: public Resource
124 friend class MenuBar
;
125 friend class MenuBarWindow
;
126 friend class MenuButton
;
127 friend class MenuFloatingWindow
;
128 friend class PopupMenu
;
129 friend class SystemWindow
;
130 friend struct ImplMenuDelData
;
132 ImplMenuDelData
* mpFirstDel
;
133 MenuItemList
* pItemList
; // Liste mit den MenuItems
136 VclPtr
<vcl::Window
> pWindow
;
138 Link
<Menu
*, bool> aActivateHdl
; // Active-Handler
139 Link
<Menu
*, bool> aDeactivateHdl
; // Deactivate-Handler
140 Link
<Menu
*, bool> aHighlightHdl
; // Highlight-Handler
141 Link
<> aSelectHdl
; // Highlight-Handler
143 VclEventListeners maEventListeners
;
144 VclEventListeners maChildEventListeners
;
146 OUString aTitleText
; // PopupMenu text
147 sal_uInt16 nTitleHeight
;
149 ImplSVEvent
* nEventId
;
150 sal_uInt16 mnHighlightedItemPos
; // for native menus: keeps track of the highlighted item
151 MenuFlags nMenuFlags
;
152 sal_uInt16 nDefaultItem
; // Id of default item
153 sal_uInt16 nSelectedId
;
156 sal_uInt16 nImgOrChkPos
;
159 bool bCanceled
: 1; ///< Terminated during a callback
160 bool bInCallback
: 1; ///< In Activate/Deactivate
161 bool bKilled
: 1; ///< Killed
163 css::uno::Reference
<css::accessibility::XAccessible
> mxAccessible
;
164 mutable vcl::MenuLayoutData
* mpLayoutData
;
168 SAL_DLLPRIVATE Menu
* ImplGetStartMenu();
169 SAL_DLLPRIVATE Menu
* ImplFindSelectMenu();
170 SAL_DLLPRIVATE Menu
* ImplFindMenu( sal_uInt16 nId
);
171 SAL_DLLPRIVATE Size
ImplCalcSize( vcl::Window
* pWin
);
172 SAL_DLLPRIVATE
bool ImplIsVisible( sal_uInt16 nPos
) const;
173 SAL_DLLPRIVATE
bool ImplIsSelectable( sal_uInt16 nPos
) const;
174 SAL_DLLPRIVATE sal_uInt16
ImplGetVisibleItemCount() const;
175 SAL_DLLPRIVATE sal_uInt16
ImplGetFirstVisible() const;
176 SAL_DLLPRIVATE sal_uInt16
ImplGetPrevVisible( sal_uInt16 nPos
) const;
177 SAL_DLLPRIVATE sal_uInt16
ImplGetNextVisible( sal_uInt16 nPos
) const;
178 SAL_DLLPRIVATE
void ImplPaint(vcl::RenderContext
& rRenderContext
,
179 sal_uInt16 nBorder
, long nOffY
= 0, MenuItemData
* pThisDataOnly
= 0,
180 bool bHighlighted
= false, bool bLayout
= false, bool bRollover
= false ) const;
181 SAL_DLLPRIVATE
void ImplPaintMenuTitle(vcl::RenderContext
&, const Rectangle
& rRect
) const;
182 SAL_DLLPRIVATE
void ImplSelect();
183 SAL_DLLPRIVATE
void ImplCallHighlight( sal_uInt16 nHighlightItem
);
184 SAL_DLLPRIVATE
void ImplCallEventListeners( sal_uLong nEvent
, sal_uInt16 nPos
);
185 DECL_DLLPRIVATE_LINK(ImplCallSelect
, void* );
187 SAL_DLLPRIVATE
void ImplFillLayoutData() const;
188 SAL_DLLPRIVATE SalMenu
* ImplGetSalMenu() { return mpSalMenu
; }
189 SAL_DLLPRIVATE
void ImplSetSalMenu( SalMenu
*pMenu
);
190 SAL_DLLPRIVATE OUString
ImplGetHelpText( sal_uInt16 nItemId
) const;
192 // returns native check and option menu symbol height in rCheckHeight and rRadioHeight
193 // return value is maximum width and height of checkboxes and radiobuttons
194 SAL_DLLPRIVATE Size
ImplGetNativeCheckAndRadioSize(vcl::RenderContext
& rRenderContext
, long& rCheckHeight
, long& rRadioHeight
) const;
196 // returns native submenu arrow size and spacing from right border
197 // return value is whether it's supported natively
198 SAL_DLLPRIVATE
bool ImplGetNativeSubmenuArrowSize(vcl::RenderContext
& rRenderContext
, Size
& rArrowSize
, long& rArrowSpacing
) const;
200 SAL_DLLPRIVATE
void ImplAddDel( ImplMenuDelData
&rDel
);
201 SAL_DLLPRIVATE
void ImplRemoveDel( ImplMenuDelData
&rDel
);
203 SAL_DLLPRIVATE MenuItemData
* NbcInsertItem(sal_uInt16 nId
, MenuItemBits nBits
,
204 const OUString
& rStr
, Menu
* pMenu
,
205 size_t nPos
, const OString
&rIdent
);
207 /// Close the 'pStartedFrom' menu window.
208 virtual void ClosePopup(Menu
* pMenu
) = 0;
210 /// Deactivate the MenuBarWindow.
211 virtual sal_uLong
DeactivateMenuBar(sal_uLong nFocusId
);
213 /// Forward the KeyInput call to the MenuBar.
214 virtual void MenuBarKeyInput(const KeyEvent
& rEvent
);
217 SAL_DLLPRIVATE
void ImplKillLayoutData() const;
218 SAL_DLLPRIVATE Menu
* ImplGetStartedFrom() const { return pStartedFrom
; }
220 SAL_DLLPRIVATE
vcl::Window
* ImplGetWindow() const { return pWindow
; }
221 void ImplSelectWithStart( Menu
* pStartMenu
= NULL
);
225 /** The Menu constructor is protected.
227 The callers are supposed to instantiate either PopupMenu or MenuBar, but
237 virtual void Highlight();
238 virtual void Select();
240 void InsertItem(sal_uInt16 nItemId
, const OUString
& rStr
,
241 MenuItemBits nItemBits
= MenuItemBits::NONE
,
242 const OString
&rIdent
= OString(),
243 sal_uInt16 nPos
= MENU_APPEND
);
244 void InsertItem(sal_uInt16 nItemId
, const Image
& rImage
,
245 MenuItemBits nItemBits
= MenuItemBits::NONE
,
246 const OString
&rIdent
= OString(),
247 sal_uInt16 nPos
= MENU_APPEND
);
248 void InsertItem(sal_uInt16 nItemId
,
249 const OUString
& rString
, const Image
& rImage
,
250 MenuItemBits nItemBits
= MenuItemBits::NONE
,
251 const OString
&rIdent
= OString(),
252 sal_uInt16 nPos
= MENU_APPEND
);
253 void InsertItem(const ResId
& rResId
, sal_uInt16 nPos
= MENU_APPEND
);
254 void InsertSeparator(const OString
&rIdent
= OString(), sal_uInt16 nPos
= MENU_APPEND
);
255 void RemoveItem( sal_uInt16 nPos
);
256 void CopyItem(const Menu
& rMenu
, sal_uInt16 nPos
, sal_uInt16 nNewPos
= MENU_APPEND
);
259 void CreateAutoMnemonics();
261 void SetMenuFlags( MenuFlags nFlags
) { nMenuFlags
= nFlags
; }
262 MenuFlags
GetMenuFlags() const { return nMenuFlags
; }
264 sal_uInt16
GetItemCount() const;
265 sal_uInt16
GetItemId(sal_uInt16 nPos
) const;
266 sal_uInt16
GetItemId(const OString
&rIdent
) const;
267 sal_uInt16
GetItemPos( sal_uInt16 nItemId
) const;
268 OString
GetItemIdent(sal_uInt16 nItemId
) const;
269 MenuItemType
GetItemType( sal_uInt16 nPos
) const;
270 sal_uInt16
GetCurItemId() const { return nSelectedId
;}
271 OString
GetCurItemIdent() const;
273 void SetDefaultItem( sal_uInt16 nItemId
) { nDefaultItem
= nItemId
; }
274 sal_uInt16
GetDefaultItem() const { return nDefaultItem
; }
276 void SetItemBits( sal_uInt16 nItemId
, MenuItemBits nBits
);
277 MenuItemBits
GetItemBits( sal_uInt16 nItemId
) const;
279 void SetUserValue(sal_uInt16 nItemId
, sal_uLong nValue
, MenuUserDataReleaseFunction aFunc
=0);
280 sal_uLong
GetUserValue(sal_uInt16 nItemId
) const;
282 void SetPopupMenu( sal_uInt16 nItemId
, PopupMenu
* pMenu
);
283 PopupMenu
* GetPopupMenu( sal_uInt16 nItemId
) const;
285 void SetAccelKey( sal_uInt16 nItemId
, const vcl::KeyCode
& rKeyCode
);
286 vcl::KeyCode
GetAccelKey( sal_uInt16 nItemId
) const;
288 void CheckItem( sal_uInt16 nItemId
, bool bCheck
= true );
289 bool IsItemChecked( sal_uInt16 nItemId
) const;
291 virtual void SelectItem(sal_uInt16 nItemId
) = 0;
292 void DeSelect() { SelectItem( 0xFFFF ); } // MENUITEMPOS_INVALID
294 void EnableItem( sal_uInt16 nItemId
, bool bEnable
= true );
295 void EnableItem(const OString
&rIdent
, bool bEnable
= true)
297 EnableItem(GetItemId(rIdent
), bEnable
);
299 bool IsItemEnabled( sal_uInt16 nItemId
) const;
301 void ShowItem( sal_uInt16 nItemId
, bool bVisible
= true );
302 void HideItem( sal_uInt16 nItemId
) { ShowItem( nItemId
, false ); }
304 bool IsItemPosVisible( sal_uInt16 nItemPos
) const;
305 bool IsMenuVisible() const;
306 virtual bool IsMenuBar() const = 0;
308 void RemoveDisabledEntries( bool bCheckPopups
= true, bool bRemoveEmptyPopups
= false );
309 bool HasValidEntries( bool bCheckPopups
= true );
311 void SetItemText( sal_uInt16 nItemId
, const OUString
& rStr
);
312 OUString
GetItemText( sal_uInt16 nItemId
) const;
314 void SetItemImage( sal_uInt16 nItemId
, const Image
& rImage
);
315 Image
GetItemImage( sal_uInt16 nItemId
) const;
316 void SetItemImageAngle( sal_uInt16 nItemId
, long nAngle10
);
317 void SetItemImageMirrorMode( sal_uInt16 nItemId
, bool bMirror
);
319 void SetItemCommand( sal_uInt16 nItemId
, const OUString
& rCommand
);
320 OUString
GetItemCommand( sal_uInt16 nItemId
) const;
322 void SetHelpText( sal_uInt16 nItemId
, const OUString
& rString
);
323 OUString
GetHelpText( sal_uInt16 nItemId
) const;
325 void SetTipHelpText( sal_uInt16 nItemId
, const OUString
& rString
);
326 OUString
GetTipHelpText( sal_uInt16 nItemId
) const;
328 void SetHelpCommand( sal_uInt16 nItemId
, const OUString
& rString
);
329 OUString
GetHelpCommand( sal_uInt16 nItemId
) const;
331 void SetHelpId( sal_uInt16 nItemId
, const OString
& rHelpId
);
332 OString
GetHelpId( sal_uInt16 nItemId
) const;
334 void SetActivateHdl( const Link
<Menu
*, bool>& rLink
)
336 aActivateHdl
= rLink
;
339 void SetDeactivateHdl( const Link
<Menu
*, bool>& rLink
)
341 aDeactivateHdl
= rLink
;
344 void SetHighlightHdl( const Link
<Menu
*, bool>& rLink
)
346 aHighlightHdl
= rLink
;
349 void SetSelectHdl( const Link
<>& rLink
)
353 const Link
<>& GetSelectHdl() const
360 return pLogo
!= nullptr;
363 sal_uInt16
GetTitleHeight()
368 void AddEventListener( const Link
<>& rEventListener
);
369 void RemoveEventListener( const Link
<>& rEventListener
);
370 void AddChildEventListener( const Link
<>& rEventListener
);
371 void RemoveChildEventListener( const Link
<>& rEventListener
);
373 Menu
& operator =( const Menu
& rMenu
);
375 // Fuer Menu-'Funktionen'
376 MenuItemList
* GetItemList() const
381 // returns the system's menu handle if native menus are supported
382 // pData must point to a SystemMenuData structure
383 bool GetSystemMenuData( SystemMenuData
* pData
) const;
385 // accessibility helpers
387 // returns the bounding box for the character at index nIndex
388 // where nIndex is relative to the starting index of the item
389 // with id nItemId (in coordinates of the displaying window)
390 Rectangle
GetCharacterBounds( sal_uInt16 nItemId
, long nIndex
) const;
391 // -1 is returned if no character is at that point
392 // if an index is found the corresponding item id is filled in (else 0)
393 long GetIndexForPoint( const Point
& rPoint
, sal_uInt16
& rItemID
) const;
394 // returns the bounding rectangle for an item at pos nItemPos
395 Rectangle
GetBoundingRectangle( sal_uInt16 nItemPos
) const;
397 css::uno::Reference
<css::accessibility::XAccessible
> GetAccessible();
398 void SetAccessible(const css::uno::Reference
<css::accessibility::XAccessible
>& rxAccessible
);
400 // gets the activation key of the specified item
401 KeyEvent
GetActivationKey( sal_uInt16 nItemId
) const;
403 vcl::Window
* GetWindow() const { return pWindow
; }
405 void SetAccessibleName( sal_uInt16 nItemId
, const OUString
& rStr
);
406 OUString
GetAccessibleName( sal_uInt16 nItemId
) const;
408 // returns whether the item a position nItemPos is highlighted or not.
409 bool IsHighlighted( sal_uInt16 nItemPos
) const;
411 void HighlightItem( sal_uInt16 nItemPos
);
412 void DeHighlight() { HighlightItem( 0xFFFF ); } // MENUITEMPOS_INVALID
416 namespace vcl
{ namespace MenuInvalidator
{
418 VCL_DLLPUBLIC VclEventListeners2
* GetMenuInvalidateListeners();
419 VCL_DLLPUBLIC
void Invalidated();
423 class VCL_DLLPUBLIC MenuBar
: public Menu
428 bool mbCloseBtnVisible
: 1;
429 bool mbFloatBtnVisible
: 1;
430 bool mbHideBtnVisible
: 1;
431 bool mbDisplayable
: 1;
433 friend class Application
;
435 friend class MenuBarWindow
;
436 friend class MenuFloatingWindow
;
437 friend class SystemWindow
;
439 SAL_DLLPRIVATE
static vcl::Window
* ImplCreate(vcl::Window
* pParent
, vcl::Window
* pWindow
,
440 MenuBar
* pMenu
, const css::uno::Reference
<css::frame::XFrame
> &rFrame
);
441 SAL_DLLPRIVATE
static void ImplDestroy(MenuBar
* pMenu
, bool bDelete
);
442 SAL_DLLPRIVATE
bool ImplHandleKeyEvent(const KeyEvent
& rKEvent
, bool bFromMenu
= true);
446 /// Return the IMenuBarWindow interface.
447 IMenuBarWindow
* getMenuBarWindow();
451 MenuBar( const MenuBar
& rMenu
);
454 MenuBar
& operator =( const MenuBar
& rMenu
);
456 virtual bool IsMenuBar() const SAL_OVERRIDE
{ return true; }
458 /// Close the 'pStartedFrom' menu window.
459 virtual void ClosePopup(Menu
* pMenu
) SAL_OVERRIDE
;
461 /// Deactivate the MenuBarWindow.
462 virtual sal_uLong
DeactivateMenuBar(sal_uLong nFocusId
) SAL_OVERRIDE
;
464 /// Forward the KeyInput call to the MenuBar.
465 virtual void MenuBarKeyInput(const KeyEvent
& rEvent
) SAL_OVERRIDE
;
467 void ShowCloseButton( bool bShow
= true );
468 bool HasCloseButton() const { return mbCloseBtnVisible
; }
469 bool HasFloatButton() const { return mbFloatBtnVisible
; }
470 bool HasHideButton() const { return mbHideBtnVisible
; }
471 void ShowButtons( bool bClose
, bool bFloat
, bool bHide
);
473 virtual void SelectItem(sal_uInt16 nId
) SAL_OVERRIDE
;
474 bool HandleMenuActivateEvent(Menu
*pMenu
) const;
475 bool HandleMenuDeActivateEvent(Menu
*pMenu
) const;
476 bool HandleMenuHighlightEvent(Menu
*pMenu
, sal_uInt16 nEventId
) const;
477 bool HandleMenuCommandEvent(Menu
*pMenu
, sal_uInt16 nEventId
) const;
478 bool HandleMenuButtonEvent(Menu
*pMenu
, sal_uInt16 nEventId
);
480 void SetCloseButtonClickHdl( const Link
<>& rLink
) { maCloseHdl
= rLink
; }
481 const Link
<>& GetCloseButtonClickHdl() const { return maCloseHdl
; }
482 void SetFloatButtonClickHdl( const Link
<>& rLink
) { maFloatHdl
= rLink
; }
483 const Link
<>& GetFloatButtonClickHdl() const { return maFloatHdl
; }
484 void SetHideButtonClickHdl( const Link
<>& rLink
) { maHideHdl
= rLink
; }
485 const Link
<>& GetHideButtonClickHdl() const { return maHideHdl
; }
487 // - by default a menubar is displayable
488 // - if a menubar is not displayable, its MenuBarWindow will never be shown
489 // and it will be hidden if it was visible before
490 // - note: if a menubar is diplayable, this does not necessarily mean that it is currently visible
491 void SetDisplayable( bool bDisplayable
);
492 bool IsDisplayable() const { return mbDisplayable
; }
494 struct MenuBarButtonCallbackArg
496 sal_uInt16 nId
; // Id of the button
497 bool bHighlight
; // highlight on/off
498 MenuBar
* pMenuBar
; // menubar the button belongs to
500 // add an arbitrary button to the menubar (will appear next to closer)
501 // passed link will be call with a MenuBarButtonCallbackArg on press
502 // passed string will be set as tooltip
503 sal_uInt16
AddMenuBarButton( const Image
&, const Link
<>&, const OUString
&, sal_uInt16 nPos
= 0 );
504 // set the highlight link for additional button with ID nId
505 // highlight link will be called with a MenuBarButtonHighlightArg
506 // the bHighlight member of that struct shall contain the new state
507 void SetMenuBarButtonHighlightHdl( sal_uInt16 nId
, const Link
<>& );
508 // returns the rectangle occupied by the additional button named nId
509 // coordinates are relative to the systemwindiow the menubar is attached to
510 // if the menubar is unattached an empty rectangle is returned
511 Rectangle
GetMenuBarButtonRectPixel( sal_uInt16 nId
);
512 void RemoveMenuBarButton( sal_uInt16 nId
);
515 inline MenuBar
& MenuBar::operator=( const MenuBar
& rMenu
)
517 Menu::operator=(rMenu
);
521 class VCL_DLLPUBLIC PopupMenu
: public Menu
524 friend class MenuFloatingWindow
;
525 friend class MenuBarWindow
;
526 friend struct MenuItemData
;
529 Menu
** pRefAutoSubMenu
; // keeps track if a pointer to this Menu is stored in the MenuItemData
531 SAL_DLLPRIVATE MenuFloatingWindow
* ImplGetFloatingWindow() const;
534 SAL_DLLPRIVATE sal_uInt16
ImplExecute( vcl::Window
* pWindow
, const Rectangle
& rRect
, FloatWinPopupFlags nPopupFlags
, Menu
* pStaredFrom
, bool bPreSelectFirst
);
535 SAL_DLLPRIVATE
long ImplCalcHeight( sal_uInt16 nEntries
) const;
536 SAL_DLLPRIVATE sal_uInt16
ImplCalcVisEntries( long nMaxHeight
, sal_uInt16 nStartEntry
= 0, sal_uInt16
* pLastVisible
= NULL
) const;
540 PopupMenu( const PopupMenu
& rMenu
);
541 explicit PopupMenu( const ResId
& );
542 virtual ~PopupMenu();
544 virtual bool IsMenuBar() const SAL_OVERRIDE
{ return false; }
546 /// Close the 'pStartedFrom' menu window.
547 virtual void ClosePopup(Menu
* pMenu
) SAL_OVERRIDE
;
549 void SetText( const OUString
& rTitle
)
553 const OUString
& GetText() const
558 sal_uInt16
Execute( vcl::Window
* pWindow
, const Point
& rPopupPos
);
559 sal_uInt16
Execute( vcl::Window
* pWindow
, const Rectangle
& rRect
, PopupMenuFlags nFlags
= PopupMenuFlags::NONE
);
562 void EndExecute( sal_uInt16 nSelect
= 0 );
563 virtual void SelectItem(sal_uInt16 nId
) SAL_OVERRIDE
;
564 void SetSelectedEntry( sal_uInt16 nId
); // for use by native submenu only
566 static bool IsInExecute();
567 static PopupMenu
* GetActivePopupMenu();
569 PopupMenu
& operator=( const PopupMenu
& rMenu
);
572 inline PopupMenu
& PopupMenu::operator=( const PopupMenu
& rMenu
)
574 Menu::operator=( rMenu
);
578 #endif // INCLUDED_VCL_MENU_HXX
580 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */