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
24 #include <rsc/rsc-vcl-shared-types.hxx>
25 #include <tools/color.hxx>
26 #include <tools/solar.h>
27 #include <vcl/dllapi.h>
28 #include <vcl/bitmapex.hxx>
29 #include <vcl/keycod.hxx>
30 #include <vcl/vclreferencebase.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>
41 namespace tools
{ class Rectangle
; }
49 class MenuFloatingWindow
;
52 struct SystemMenuData
;
53 enum class FloatWinPopupFlags
;
55 namespace com
{ namespace sun
{ namespace star
{ namespace accessibility
{
62 struct MenuLayoutData
;
63 typedef OutputDevice RenderContext
; // same as in include/vcl/outdev.hxx
66 #define MENU_APPEND (sal_uInt16(0xFFFF))
67 #define MENU_ITEM_NOTFOUND (sal_uInt16(0xFFFF))
69 // Must match the definitions in css::awt::PopupMenuDirection.idl
70 enum class PopupMenuFlags
76 ExecuteRight
= 0x0008,
77 NoMouseUpClose
= 0x0010,
78 //If there isn't enough space to put the menu where it wants
79 //to go, then they will be autoplaced. Toggle this bit
80 //on to force menus to be placed either above or below
81 //the starting rectangle and shrunk to fit and then scroll rather than place
82 //the menu beside that rectangle
83 NoHorzPlacement
= 0x0020,
88 template<> struct typed_flags
<PopupMenuFlags
> : is_typed_flags
<PopupMenuFlags
, 0x003f> {};
94 NoAutoMnemonics
= 0x0001,
95 HideDisabledEntries
= 0x0002,
96 // overrides default hiding of disabled entries in popup menus
97 AlwaysShowDisabledEntries
= 0x0004,
102 template<> struct typed_flags
<MenuFlags
> : is_typed_flags
<MenuFlags
, 0x0007> {};
105 /// Invalid menu item id
106 #define ITEMPOS_INVALID 0xFFFF
108 struct ImplMenuDelData
110 ImplMenuDelData
* mpNext
;
111 VclPtr
<const Menu
> mpMenu
;
113 explicit ImplMenuDelData( const Menu
* );
116 bool isDeleted() const { return mpMenu
== nullptr; }
126 typedef void (*MenuUserDataReleaseFunction
)(sal_uLong
);
128 class VCL_DLLPUBLIC Menu
: public VclReferenceBase
130 friend class MenuBar
;
131 friend class MenuBarWindow
;
132 friend class MenuButton
;
133 friend class MenuFloatingWindow
;
134 friend class PopupMenu
;
135 friend class SystemWindow
;
136 friend struct ImplMenuDelData
;
138 ImplMenuDelData
* mpFirstDel
;
139 std::unique_ptr
<MenuItemList
> pItemList
; // list with MenuItems
141 VclPtr
<Menu
> pStartedFrom
;
142 VclPtr
<vcl::Window
> pWindow
;
144 Link
<Menu
*, bool> aActivateHdl
; // Active-Handler
145 Link
<Menu
*, bool> aDeactivateHdl
; // Deactivate-Handler
146 Link
<Menu
*, bool> aSelectHdl
; // Select-Handler
148 std::list
<Link
<VclMenuEvent
&,void> > maEventListeners
;
150 OUString aTitleText
; // PopupMenu text
151 sal_uInt16 nTitleHeight
;
153 ImplSVEvent
* nEventId
;
154 sal_uInt16 mnHighlightedItemPos
; // for native menus: keeps track of the highlighted item
155 MenuFlags nMenuFlags
;
156 sal_uInt16 nSelectedId
;
159 sal_uInt16 nImgOrChkPos
;
162 bool bCanceled
: 1; ///< Terminated during a callback
163 bool bInCallback
: 1; ///< In Activate/Deactivate
164 bool bKilled
: 1; ///< Killed
166 css::uno::Reference
<css::accessibility::XAccessible
> mxAccessible
;
167 mutable vcl::MenuLayoutData
* mpLayoutData
;
171 SAL_DLLPRIVATE Menu
* ImplGetStartMenu();
172 SAL_DLLPRIVATE Menu
* ImplFindSelectMenu();
173 SAL_DLLPRIVATE Menu
* ImplFindMenu( sal_uInt16 nId
);
174 SAL_DLLPRIVATE Size
ImplCalcSize( vcl::Window
* pWin
);
175 SAL_DLLPRIVATE
bool ImplIsVisible( sal_uInt16 nPos
) const;
176 SAL_DLLPRIVATE
bool ImplIsSelectable( sal_uInt16 nPos
) const;
177 SAL_DLLPRIVATE sal_uInt16
ImplGetVisibleItemCount() const;
178 SAL_DLLPRIVATE sal_uInt16
ImplGetFirstVisible() const;
179 SAL_DLLPRIVATE sal_uInt16
ImplGetPrevVisible( sal_uInt16 nPos
) const;
180 SAL_DLLPRIVATE sal_uInt16
ImplGetNextVisible( sal_uInt16 nPos
) const;
181 SAL_DLLPRIVATE
void ImplPaint(vcl::RenderContext
& rRenderContext
,
182 sal_uInt16 nBorder
, long nOffY
= 0, MenuItemData
* pThisDataOnly
= nullptr,
183 bool bHighlighted
= false, bool bLayout
= false, bool bRollover
= false ) const;
184 SAL_DLLPRIVATE
void ImplPaintMenuTitle(vcl::RenderContext
&, const tools::Rectangle
& rRect
) const;
185 SAL_DLLPRIVATE
void ImplSelect();
186 SAL_DLLPRIVATE
void ImplCallHighlight( sal_uInt16 nHighlightItem
);
187 SAL_DLLPRIVATE
void ImplCallEventListeners( VclEventId nEvent
, sal_uInt16 nPos
);
188 DECL_DLLPRIVATE_LINK(ImplCallSelect
, void*, void );
190 SAL_DLLPRIVATE
void ImplFillLayoutData() const;
191 SAL_DLLPRIVATE SalMenu
* ImplGetSalMenu() { return mpSalMenu
; }
192 SAL_DLLPRIVATE
void ImplClearSalMenu();
193 SAL_DLLPRIVATE OUString
ImplGetHelpText( sal_uInt16 nItemId
) const;
195 // returns native check and option menu symbol height in rCheckHeight and rRadioHeight
196 // return value is maximum width and height of checkboxes and radiobuttons
197 SAL_DLLPRIVATE Size
ImplGetNativeCheckAndRadioSize(vcl::RenderContext
& rRenderContext
, long& rCheckHeight
, long& rRadioHeight
) const;
199 // returns native submenu arrow size and spacing from right border
200 // return value is whether it's supported natively
201 SAL_DLLPRIVATE
static bool ImplGetNativeSubmenuArrowSize(vcl::RenderContext
& rRenderContext
, Size
& rArrowSize
, long& rArrowSpacing
);
203 SAL_DLLPRIVATE
void ImplAddDel( ImplMenuDelData
&rDel
);
204 SAL_DLLPRIVATE
void ImplRemoveDel( ImplMenuDelData
&rDel
);
206 SAL_DLLPRIVATE MenuItemData
* NbcInsertItem(sal_uInt16 nId
, MenuItemBits nBits
,
207 const OUString
& rStr
, Menu
* pMenu
,
208 size_t nPos
, const OString
&rIdent
);
210 /// Close the 'pStartedFrom' menu window.
211 virtual void ClosePopup(Menu
* pMenu
) = 0;
213 /// Forward the KeyInput call to the MenuBar.
214 virtual void MenuBarKeyInput(const KeyEvent
& rEvent
);
217 SAL_DLLPRIVATE
void ImplKillLayoutData() const;
219 SAL_DLLPRIVATE
vcl::Window
* ImplGetWindow() const { return pWindow
; }
221 void ImplSelectWithStart( Menu
* pStartMenu
= nullptr );
226 /** The Menu constructor is protected.
228 The callers are supposed to instantiate either PopupMenu or MenuBar, but
234 virtual ~Menu() override
;
235 virtual void dispose() override
;
239 virtual void Select();
241 void InsertItem(sal_uInt16 nItemId
, const OUString
& rStr
,
242 MenuItemBits nItemBits
= MenuItemBits::NONE
,
243 const OString
&rIdent
= OString(),
244 sal_uInt16 nPos
= MENU_APPEND
);
245 void InsertItem(sal_uInt16 nItemId
, const Image
& rImage
,
246 MenuItemBits nItemBits
= MenuItemBits::NONE
,
247 const OString
&rIdent
= OString(),
248 sal_uInt16 nPos
= MENU_APPEND
);
249 void InsertItem(sal_uInt16 nItemId
,
250 const OUString
& rString
, const Image
& rImage
,
251 MenuItemBits nItemBits
= MenuItemBits::NONE
,
252 const OString
&rIdent
= OString(),
253 sal_uInt16 nPos
= MENU_APPEND
);
254 void InsertItem(const OUString
& rCommand
,
255 const css::uno::Reference
<css::frame::XFrame
>& rFrame
);
256 void InsertSeparator(const OString
&rIdent
= OString(), sal_uInt16 nPos
= MENU_APPEND
);
257 void RemoveItem( sal_uInt16 nPos
);
260 void CreateAutoMnemonics();
262 void SetMenuFlags( MenuFlags nFlags
) { nMenuFlags
= nFlags
; }
263 MenuFlags
GetMenuFlags() const { return nMenuFlags
; }
265 sal_uInt16
GetItemCount() const;
266 sal_uInt16
GetItemId(sal_uInt16 nPos
) const;
267 sal_uInt16
GetItemId(const OString
&rIdent
) const;
268 sal_uInt16
GetItemPos( sal_uInt16 nItemId
) const;
269 OString
GetItemIdent(sal_uInt16 nItemId
) const;
270 MenuItemType
GetItemType( sal_uInt16 nPos
) const;
271 sal_uInt16
GetCurItemId() const { return nSelectedId
;}
272 OString
GetCurItemIdent() const;
274 void SetItemBits( sal_uInt16 nItemId
, MenuItemBits nBits
);
275 MenuItemBits
GetItemBits( sal_uInt16 nItemId
) const;
277 void SetUserValue(sal_uInt16 nItemId
, sal_uLong nValue
, MenuUserDataReleaseFunction aFunc
=nullptr);
278 sal_uLong
GetUserValue(sal_uInt16 nItemId
) const;
280 void SetPopupMenu( sal_uInt16 nItemId
, PopupMenu
* pMenu
);
281 PopupMenu
* GetPopupMenu( sal_uInt16 nItemId
) const;
283 void SetAccelKey( sal_uInt16 nItemId
, const vcl::KeyCode
& rKeyCode
);
284 vcl::KeyCode
GetAccelKey( sal_uInt16 nItemId
) const;
286 void CheckItem( sal_uInt16 nItemId
, bool bCheck
= true );
287 bool IsItemChecked( sal_uInt16 nItemId
) const;
289 virtual void SelectItem(sal_uInt16 nItemId
) = 0;
291 void EnableItem( sal_uInt16 nItemId
, bool bEnable
= true );
292 void EnableItem(const OString
&rIdent
, bool bEnable
= true)
294 EnableItem(GetItemId(rIdent
), bEnable
);
296 bool IsItemEnabled( sal_uInt16 nItemId
) const;
298 void ShowItem( sal_uInt16 nItemId
, bool bVisible
= true );
299 void HideItem( sal_uInt16 nItemId
) { ShowItem( nItemId
, false ); }
301 bool IsItemPosVisible( sal_uInt16 nItemPos
) const;
302 bool IsMenuVisible() const;
303 virtual bool IsMenuBar() const = 0;
305 void RemoveDisabledEntries( bool bCheckPopups
= true, bool bRemoveEmptyPopups
= false );
306 bool HasValidEntries();
308 void UpdateNativeMenu();
310 void SetItemText( sal_uInt16 nItemId
, const OUString
& rStr
);
311 OUString
GetItemText( sal_uInt16 nItemId
) const;
313 void SetItemImage( sal_uInt16 nItemId
, const Image
& rImage
);
314 Image
GetItemImage( sal_uInt16 nItemId
) const;
316 void SetItemCommand( sal_uInt16 nItemId
, const OUString
& rCommand
);
317 OUString
GetItemCommand( sal_uInt16 nItemId
) const;
319 void SetHelpText( sal_uInt16 nItemId
, const OUString
& rString
);
320 OUString
GetHelpText( sal_uInt16 nItemId
) const;
322 void SetTipHelpText( sal_uInt16 nItemId
, const OUString
& rString
);
323 OUString
GetTipHelpText( sal_uInt16 nItemId
) const;
325 void SetHelpCommand( sal_uInt16 nItemId
, const OUString
& rString
);
326 OUString
GetHelpCommand( sal_uInt16 nItemId
) const;
328 void SetHelpId( sal_uInt16 nItemId
, const OString
& rHelpId
);
329 OString
GetHelpId( sal_uInt16 nItemId
) const;
331 void SetActivateHdl( const Link
<Menu
*, bool>& rLink
)
333 aActivateHdl
= rLink
;
336 void SetDeactivateHdl( const Link
<Menu
*, bool>& rLink
)
338 aDeactivateHdl
= rLink
;
341 void SetSelectHdl( const Link
<Menu
*,bool>& rLink
)
346 sal_uInt16
GetTitleHeight()
351 void AddEventListener( const Link
<VclMenuEvent
&,void>& rEventListener
);
352 void RemoveEventListener( const Link
<VclMenuEvent
&,void>& rEventListener
);
354 Menu
& operator =( const Menu
& rMenu
);
356 // for menu functions
357 MenuItemList
* GetItemList() const
359 return pItemList
.get();
362 // returns the system's menu handle if native menus are supported
363 // pData must point to a SystemMenuData structure
364 bool GetSystemMenuData( SystemMenuData
* pData
) const;
366 // accessibility helpers
368 // returns the bounding box for the character at index nIndex
369 // where nIndex is relative to the starting index of the item
370 // with id nItemId (in coordinates of the displaying window)
371 tools::Rectangle
GetCharacterBounds( sal_uInt16 nItemId
, long nIndex
) const;
372 // -1 is returned if no character is at that point
373 // if an index is found the corresponding item id is filled in (else 0)
374 long GetIndexForPoint( const Point
& rPoint
, sal_uInt16
& rItemID
) const;
375 // returns the bounding rectangle for an item at pos nItemPos
376 tools::Rectangle
GetBoundingRectangle( sal_uInt16 nItemPos
) const;
378 css::uno::Reference
<css::accessibility::XAccessible
> GetAccessible();
379 void SetAccessible(const css::uno::Reference
<css::accessibility::XAccessible
>& rxAccessible
);
381 // gets the activation key of the specified item
382 KeyEvent
GetActivationKey( sal_uInt16 nItemId
) const;
384 vcl::Window
* GetWindow() const { return pWindow
; }
386 OUString
GetAccessibleName( sal_uInt16 nItemId
) const;
388 // returns whether the item a position nItemPos is highlighted or not.
389 bool IsHighlighted( sal_uInt16 nItemPos
) const;
391 void HighlightItem( sal_uInt16 nItemPos
);
392 void DeHighlight() { HighlightItem( 0xFFFF ); } // MENUITEMPOS_INVALID
394 bool HandleMenuCommandEvent(Menu
*pMenu
, sal_uInt16 nEventId
) const;
395 bool HandleMenuActivateEvent(Menu
*pMenu
) const;
396 bool HandleMenuDeActivateEvent(Menu
*pMenu
) const;
399 class VCL_DLLPUBLIC MenuBar
: public Menu
401 Link
<void*,void> maCloseHdl
;
402 bool mbCloseBtnVisible
: 1;
403 bool mbFloatBtnVisible
: 1;
404 bool mbHideBtnVisible
: 1;
405 bool mbDisplayable
: 1;
407 friend class Application
;
409 friend class MenuBarWindow
;
410 friend class MenuFloatingWindow
;
411 friend class SystemWindow
;
413 SAL_DLLPRIVATE
static VclPtr
<vcl::Window
> ImplCreate(vcl::Window
* pParent
, vcl::Window
* pWindow
, MenuBar
* pMenu
);
414 SAL_DLLPRIVATE
static void ImplDestroy(MenuBar
* pMenu
, bool bDelete
);
415 SAL_DLLPRIVATE
bool ImplHandleKeyEvent(const KeyEvent
& rKEvent
);
416 SAL_DLLPRIVATE
bool ImplHandleCmdEvent(const CommandEvent
& rCEvent
);
420 /// Return the MenuBarWindow.
421 MenuBarWindow
* getMenuBarWindow();
425 MenuBar( const MenuBar
& rMenu
);
426 virtual ~MenuBar() override
;
427 virtual void dispose() override
;
429 MenuBar
& operator =( const MenuBar
& rMenu
);
431 virtual bool IsMenuBar() const override
{ return true; }
433 /// Close the 'pStartedFrom' menu window.
434 virtual void ClosePopup(Menu
* pMenu
) override
;
436 /// Forward the KeyInput call to the MenuBar.
437 virtual void MenuBarKeyInput(const KeyEvent
& rEvent
) override
;
439 void ShowCloseButton( bool bShow
);
440 bool HasCloseButton() const { return mbCloseBtnVisible
; }
441 bool HasFloatButton() const { return mbFloatBtnVisible
; }
442 bool HasHideButton() const { return mbHideBtnVisible
; }
443 void ShowButtons( bool bClose
, bool bFloat
, bool bHide
);
445 virtual void SelectItem(sal_uInt16 nId
) override
;
446 bool HandleMenuHighlightEvent(Menu
*pMenu
, sal_uInt16 nEventId
) const;
447 bool HandleMenuButtonEvent(sal_uInt16 nEventId
);
449 void SetCloseButtonClickHdl( const Link
<void*,void>& rLink
) { maCloseHdl
= rLink
; }
450 const Link
<void*,void>& GetCloseButtonClickHdl() const { return maCloseHdl
; }
452 // - by default a menubar is displayable
453 // - if a menubar is not displayable, its MenuBarWindow will never be shown
454 // and it will be hidden if it was visible before
455 // - note: if a menubar is displayable, this does not necessarily mean that it is currently visible
456 void SetDisplayable( bool bDisplayable
);
457 bool IsDisplayable() const { return mbDisplayable
; }
459 struct MenuBarButtonCallbackArg
461 sal_uInt16 nId
; // Id of the button
462 bool bHighlight
; // highlight on/off
463 VclPtr
<MenuBar
> pMenuBar
; // menubar the button belongs to
465 // add an arbitrary button to the menubar (will appear next to closer)
466 // passed link will be call with a MenuBarButtonCallbackArg on press
467 // passed string will be set as tooltip
468 sal_uInt16
AddMenuBarButton( const Image
&, const Link
<MenuBar::MenuBarButtonCallbackArg
&,bool>&, const OUString
& );
469 // set the highlight link for additional button with ID nId
470 // highlight link will be called with a MenuBarButtonHighlightArg
471 // the bHighlight member of that struct shall contain the new state
472 void SetMenuBarButtonHighlightHdl( sal_uInt16 nId
, const Link
<MenuBar::MenuBarButtonCallbackArg
&,bool>& );
473 // returns the rectangle occupied by the additional button named nId
474 // coordinates are relative to the systemwindow the menubar is attached to
475 // if the menubar is unattached an empty rectangle is returned
476 tools::Rectangle
GetMenuBarButtonRectPixel( sal_uInt16 nId
);
477 void RemoveMenuBarButton( sal_uInt16 nId
);
478 void LayoutChanged();
481 inline MenuBar
& MenuBar::operator=( const MenuBar
& rMenu
)
483 Menu::operator=(rMenu
);
487 class VCL_DLLPUBLIC PopupMenu
: public Menu
490 friend class MenuFloatingWindow
;
491 friend class MenuBarWindow
;
492 friend struct MenuItemData
;
495 SAL_DLLPRIVATE MenuFloatingWindow
* ImplGetFloatingWindow() const;
498 SAL_DLLPRIVATE sal_uInt16
ImplExecute( const VclPtr
<vcl::Window
>& pW
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nPopupModeFlags
, Menu
* pSFrom
, bool bPreSelectFirst
);
499 SAL_DLLPRIVATE
void ImplFlushPendingSelect();
500 SAL_DLLPRIVATE
long ImplCalcHeight( sal_uInt16 nEntries
) const;
501 SAL_DLLPRIVATE sal_uInt16
ImplCalcVisEntries( long nMaxHeight
, sal_uInt16 nStartEntry
, sal_uInt16
* pLastVisible
= nullptr ) const;
505 PopupMenu( const PopupMenu
& rMenu
);
506 virtual ~PopupMenu() override
;
508 virtual bool IsMenuBar() const override
{ return false; }
510 /// Close the 'pStartedFrom' menu window.
511 virtual void ClosePopup(Menu
* pMenu
) override
;
513 void SetText( const OUString
& rTitle
)
518 sal_uInt16
Execute( vcl::Window
* pWindow
, const Point
& rPopupPos
);
519 sal_uInt16
Execute( vcl::Window
* pWindow
, const tools::Rectangle
& rRect
, PopupMenuFlags nFlags
= PopupMenuFlags::NONE
);
523 virtual void SelectItem(sal_uInt16 nId
) override
;
524 void SetSelectedEntry( sal_uInt16 nId
); // for use by native submenu only
526 static bool IsInExecute();
527 static PopupMenu
* GetActivePopupMenu();
529 PopupMenu
& operator=( const PopupMenu
& rMenu
);
532 inline PopupMenu
& PopupMenu::operator=( const PopupMenu
& rMenu
)
534 Menu::operator=( rMenu
);
538 #endif // INCLUDED_VCL_MENU_HXX
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */