LibreOffice Module vcl (master)  1
menubtn.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/dockwin.hxx>
21 #include <vcl/event.hxx>
22 #include <vcl/toolkit/floatwin.hxx>
23 #include <vcl/menu.hxx>
24 #include <vcl/timer.hxx>
25 #include <vcl/toolkit/menubtn.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/uitest/uiobject.hxx>
28 #include <vcl/uitest/logger.hxx>
30 #include <menutogglebutton.hxx>
31 #include <tools/json_writer.hxx>
32 
33 namespace
34 {
35 void collectUIInformation( const OUString& aID, const OUString& aevent , const OUString& akey , const OUString& avalue)
36 {
37  EventDescription aDescription;
38  aDescription.aID = aID;
39  aDescription.aParameters = {{ akey , avalue}};
40  aDescription.aAction = aevent;
41  aDescription.aParent = "MainWindow";
42  aDescription.aKeyWord = "MenuButton";
43  UITestLogger::getInstance().logEvent(aDescription);
44 }
45 }
46 
47 void MenuButton::ImplInit( vcl::Window* pParent, WinBits nStyle )
48 {
49  if ( !(nStyle & WB_NOTABSTOP) )
50  nStyle |= WB_TABSTOP;
51 
52  PushButton::ImplInit( pParent, nStyle );
54 }
55 
57 {
58  mbStartingMenu = true;
59 
60  Activate();
61 
62  if (!mpMenu && !mpFloatingWindow)
63  {
64  mbStartingMenu = false;
65  return;
66  }
67 
68  Size aSize = GetSizePixel();
69  SetPressed( true );
70  EndSelection();
71  if (mpMenu)
72  {
73  Point aPos(0, 1);
74  tools::Rectangle aRect(aPos, aSize );
76 
77  if (isDisposed())
78  return;
79 
82  }
83  else
84  {
86  tools::Rectangle aRect(aPos, aSize );
88  if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW)
89  static_cast<FloatingWindow*>(mpFloatingWindow.get())->StartPopupMode(aRect, nFlags);
90  else
91  {
92  mpFloatingWindow->EnableDocking();
94  }
95  }
96 
97  mbStartingMenu = false;
98 
99  SetPressed(false);
100  OUString aID = get_id(); // tdf#136678 take a copy if we are destroyed by Select callback
101  if (mnCurItemId)
102  {
103  Select();
104  mnCurItemId = 0;
105  msCurItemIdent.clear();
106  }
107  collectUIInformation(aID,"OPENLIST","","");
108 }
109 
111 {
112  if (!mpMenu && !mpFloatingWindow)
113  return;
114 
115  if (mpMenu)
116  {
117  mpMenu->EndExecute();
118  }
119  else
120  {
121  if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW)
122  static_cast<FloatingWindow*>(mpFloatingWindow.get())->EndPopupMode();
123  else
125  }
126  collectUIInformation(get_id(),"CLOSELIST","","");
127 }
128 
130 {
131  if (mbStartingMenu)
132  return true;
133 
134  if (!mpMenu && !mpFloatingWindow)
135  return false;
136 
137  if (mpMenu)
139  else
140  {
141  if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW)
142  return static_cast<const FloatingWindow*>(mpFloatingWindow.get())->IsInPopupMode();
143  else
145  }
146 }
147 
150  , mnCurItemId(0)
151  , mbDelayMenu(false)
152  , mbStartingMenu(false)
153 {
155  ImplInit(pParent, nWinBits);
156 }
157 
159 {
160  disposeOnce();
161 }
162 
164 {
165  mpMenuTimer.reset();
167  mpMenu.clear();
169 }
170 
171 IMPL_LINK_NOARG(MenuButton, ImplMenuTimeoutHdl, Timer *, void)
172 {
173  // See if Button Tracking is still active, as it could've been cancelled earlier
174  if ( IsTracking() )
175  {
176  if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
177  GrabFocus();
178  ExecuteMenu();
179  }
180 }
181 
183 {
184  bool bExecute = true;
185  if (mbDelayMenu)
186  {
187  // If the separated dropdown symbol is not hit, delay the popup execution
188  if( rMEvt.GetPosPixel().X() <= ImplGetSeparatorX() )
189  {
190  if ( !mpMenuTimer )
191  {
192  mpMenuTimer.reset(new Timer("MenuTimer"));
193  mpMenuTimer->SetInvokeHandler( LINK( this, MenuButton, ImplMenuTimeoutHdl ) );
194  }
195 
197  mpMenuTimer->Start();
198 
200  bExecute = false;
201  }
202  }
203  if( bExecute )
204  {
205  if ( PushButton::ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) )
206  {
207  if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
208  GrabFocus();
209  ExecuteMenu();
210  }
211  }
212 }
213 
214 void MenuButton::KeyInput( const KeyEvent& rKEvt )
215 {
216  vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
217  sal_uInt16 nCode = aKeyCode.GetCode();
218  if ( (nCode == KEY_DOWN) && aKeyCode.IsMod2() )
219  ExecuteMenu();
220  else if ( !mbDelayMenu &&
221  !aKeyCode.GetModifier() &&
222  ((nCode == KEY_RETURN) || (nCode == KEY_SPACE)) )
223  ExecuteMenu();
224  else
225  PushButton::KeyInput( rKEvt );
226 }
227 
229 {
230  maActivateHdl.Call( this );
231 }
232 
234 {
235  if (mnCurItemId)
236  collectUIInformation(get_id(),"OPENFROMLIST","POS",OUString::number(mnCurItemId));
237 
238  maSelectHdl.Call( this );
239 }
240 
242 {
243  if (pNewMenu == mpMenu)
244  return;
245 
246  mpMenu = pNewMenu;
247 }
248 
249 void MenuButton::SetPopover(Window* pWindow)
250 {
251  if (pWindow == mpFloatingWindow)
252  return;
253 
254  mpFloatingWindow = pWindow;
255 }
256 
257 
259 {
261 }
262 
266 }
267 
268 //class MenuToggleButton ----------------------------------------------------
269 
271  : MenuButton( pParent, nWinBits )
272 {
273 }
274 
276 {
277  disposeOnce();
278 }
279 
281 {
282  mbIsActive = bSel;
283 }
284 
286 {
287  return mbIsActive;
288 }
289 
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2788
virtual void EnableRTL(bool bEnable=true) override
Definition: ctrl.cxx:64
bool mbDelayMenu
Definition: menubtn.hxx:44
void EndSelection()
Definition: button.cxx:1610
bool mbIsActive
Definition: button.hxx:184
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: button.cxx:1283
bool InPopupMode() const
Definition: menubtn.cxx:129
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: menubtn.cxx:163
MenuToggleButton(vcl::Window *pParent, WinBits nStyle)
Definition: menubtn.cxx:270
std::function< std::unique_ptr< UIObject >vcl::Window *)> FactoryFunction
virtual Size GetSizePixel() const
Definition: window.cxx:2399
sal_uInt16 GetCode() const
Definition: keycod.hxx:49
sal_uInt16 Execute(vcl::Window *pWindow, const Point &rPopupPos)
Definition: menu.cxx:2779
constexpr sal_uInt16 KEY_SPACE
Definition: keycodes.hxx:123
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: menubtn.cxx:214
FloatWinPopupFlags
Definition: vclenum.hxx:367
void SetPopover(Window *pWindow)
Definition: menubtn.cxx:249
void ExecuteMenu()
Definition: menubtn.cxx:56
Link< MenuButton *, void > maSelectHdl
Definition: menubtn.hxx:47
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: button.cxx:112
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: button.cxx:626
OString const & GetCurItemIdent() const
Definition: menu.hxx:269
WinBits const WB_NOPOINTERFOCUS
static UITestLogger & getInstance()
Definition: logger.cxx:611
void logEvent(const EventDescription &rDescription)
Definition: logger.cxx:372
sal_Int64 WinBits
const OUString & get_id() const
Get the ID of the window.
Definition: window.cxx:3925
SAL_DLLPRIVATE tools::Long ImplGetSeparatorX() const
The x-coordinate of the vertical separator line, use in MenuButton subclass only. ...
Definition: button.cxx:181
sal_uInt16 GetModifier() const
Definition: keycod.hxx:52
PushButtonDropdownStyle mnDDStyle
Definition: button.hxx:183
sal_uInt16 nCode
virtual FactoryFunction GetUITestFactory() const override
Definition: menubtn.cxx:258
sal_uInt16 mnCurItemId
Definition: menubtn.hxx:43
VclPtr< PopupMenu > mpMenu
Definition: menubtn.hxx:40
constexpr sal_uInt16 KEY_DOWN
Definition: keycodes.hxx:110
void clear()
Definition: vclptr.hxx:190
MenuButton(const MenuButton &)=delete
sal_uInt16 GetCurItemId() const
Definition: menu.hxx:268
void SetCurItemId()
Definition: menubtn.cxx:263
virtual void Activate() override
Definition: menubtn.cxx:228
static PopupMenu * GetActivePopupMenu()
Definition: menu.cxx:2730
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: menubtn.cxx:47
void CancelMenu()
Definition: menubtn.cxx:110
std::unique_ptr< Timer > mpMenuTimer
Definition: menubtn.hxx:39
static bool GetLayoutRTL()
virtual ~MenuButton() override
Definition: menubtn.cxx:158
static sal_Int32 GetActionDelay()
VclPtr< Window > mpFloatingWindow
Definition: menubtn.hxx:41
bool mbStartingMenu
Definition: menubtn.hxx:45
void GrabFocus()
Definition: window.cxx:2973
vcl::Window * GetParent() const
Definition: window2.cxx:1091
bool GetActive() const
Definition: menubtn.cxx:285
Link< MenuButton *, void > maActivateHdl
Definition: menubtn.hxx:46
constexpr sal_uInt16 KEY_RETURN
Definition: keycodes.hxx:119
bool IsInPopupMode(const vcl::Window *pWin)
Definition: dockmgr.cxx:358
void SetActive(bool bSel)
Definition: menubtn.cxx:280
OString msCurItemIdent
Definition: menubtn.hxx:42
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:57
void SetPressed(bool bPressed)
Definition: button.cxx:1601
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: menubtn.cxx:182
void EndExecute()
Definition: menu.cxx:2736
static SAL_DLLPRIVATE bool ImplHitTestPushButton(vcl::Window const *pDev, const Point &rPos)
Definition: button.cxx:742
WindowType
void Select()
Definition: menubtn.cxx:233
void SetPopupMenu(PopupMenu *pNewMenu)
Definition: menubtn.cxx:241
const Point & GetPosPixel() const
Definition: event.hxx:123
virtual ~MenuToggleButton() override
Definition: menubtn.cxx:275
void EndPopupMode(const vcl::Window *pWin)
Definition: dockmgr.cxx:364
WinBits const WB_TABSTOP
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
void StartPopupMode(const vcl::Window *pWin, const tools::Rectangle &rRect, FloatWinPopupFlags nPopupModeFlags)
Definition: dockmgr.cxx:337
WinBits GetStyle() const
Definition: window2.cxx:947
Definition: timer.hxx:26
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2800
std::map< OUString, OUString > aParameters
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: button.cxx:1200
WinBits const WB_NOTABSTOP
bool isDisposed() const
static DockingManager * GetDockingManager()
Definition: window2.cxx:792
bool IsMod2() const
Definition: keycod.hxx:58