/src/libreoffice/vcl/source/control/MenuButton.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ |
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/MenuButton.hxx> |
26 | | #include <vcl/settings.hxx> |
27 | | #include <vcl/uitest/uiobject.hxx> |
28 | | #include <vcl/uitest/logger.hxx> |
29 | | #include <vcl/uitest/eventdescription.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 | 0 | { |
37 | 0 | EventDescription aDescription; |
38 | 0 | aDescription.aID = aID; |
39 | 0 | aDescription.aParameters = {{ akey , avalue}}; |
40 | 0 | aDescription.aAction = aevent; |
41 | 0 | aDescription.aParent = "MainWindow"; |
42 | 0 | aDescription.aKeyWord = "MenuButton"; |
43 | 0 | UITestLogger::getInstance().logEvent(aDescription); |
44 | 0 | } |
45 | | } |
46 | | |
47 | | void MenuButton::ImplInit( vcl::Window* pParent, WinBits nStyle ) |
48 | 0 | { |
49 | 0 | if ( !(nStyle & WB_NOTABSTOP) ) |
50 | 0 | nStyle |= WB_TABSTOP; |
51 | |
|
52 | 0 | PushButton::ImplInit( pParent, nStyle ); |
53 | 0 | EnableRTL( AllSettings::GetLayoutRTL() ); |
54 | 0 | } |
55 | | |
56 | | void MenuButton::ExecuteMenu() |
57 | 0 | { |
58 | 0 | mbStartingMenu = true; |
59 | |
|
60 | 0 | PrepareExecute(); |
61 | |
|
62 | 0 | if (!mpMenu && !mpFloatingWindow) |
63 | 0 | { |
64 | 0 | mbStartingMenu = false; |
65 | 0 | return; |
66 | 0 | } |
67 | | |
68 | 0 | Size aSize = GetSizePixel(); |
69 | 0 | SetPressed( true ); |
70 | 0 | EndSelection(); |
71 | 0 | if (mpMenu) |
72 | 0 | { |
73 | 0 | Point aPos(0, 1); |
74 | 0 | tools::Rectangle aRect(aPos, aSize ); |
75 | 0 | mpMenu->Execute(this, aRect, PopupMenuFlags::ExecuteDown); |
76 | |
|
77 | 0 | if (isDisposed()) |
78 | 0 | return; |
79 | | |
80 | 0 | mnCurItemId = mpMenu->GetCurItemId(); |
81 | 0 | msCurItemIdent = mpMenu->GetCurItemIdent(); |
82 | 0 | } |
83 | 0 | else |
84 | 0 | { |
85 | 0 | Point aPos(GetParent()->OutputToScreenPixel(GetPosPixel())); |
86 | 0 | tools::Rectangle aRect(aPos, aSize ); |
87 | 0 | FloatWinPopupFlags nFlags = FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus; |
88 | 0 | if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW) |
89 | 0 | static_cast<FloatingWindow*>(mpFloatingWindow.get())->StartPopupMode(aRect, nFlags); |
90 | 0 | else |
91 | 0 | { |
92 | 0 | mpFloatingWindow->EnableDocking(); |
93 | 0 | vcl::Window::GetDockingManager()->StartPopupMode(mpFloatingWindow, aRect, nFlags); |
94 | 0 | } |
95 | 0 | } |
96 | | |
97 | 0 | Activate(); |
98 | |
|
99 | 0 | mbStartingMenu = false; |
100 | |
|
101 | 0 | SetPressed(false); |
102 | 0 | OUString aID = get_id(); // tdf#136678 take a copy if we are destroyed by Select callback |
103 | 0 | if (mnCurItemId) |
104 | 0 | { |
105 | 0 | Select(); |
106 | 0 | mnCurItemId = 0; |
107 | 0 | msCurItemIdent.clear(); |
108 | 0 | } |
109 | 0 | collectUIInformation(aID,u"OPENLIST"_ustr,u""_ustr,u""_ustr); |
110 | 0 | } |
111 | | |
112 | | void MenuButton::CancelMenu() |
113 | 0 | { |
114 | 0 | if (!mpMenu && !mpFloatingWindow) |
115 | 0 | return; |
116 | | |
117 | 0 | if (mpMenu) |
118 | 0 | { |
119 | 0 | mpMenu->EndExecute(); |
120 | 0 | } |
121 | 0 | else |
122 | 0 | { |
123 | 0 | if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW) |
124 | 0 | static_cast<FloatingWindow*>(mpFloatingWindow.get())->EndPopupMode(); |
125 | 0 | else |
126 | 0 | vcl::Window::GetDockingManager()->EndPopupMode(mpFloatingWindow); |
127 | 0 | } |
128 | 0 | collectUIInformation(get_id(),u"CLOSELIST"_ustr,u""_ustr,u""_ustr); |
129 | 0 | } |
130 | | |
131 | | bool MenuButton::InPopupMode() const |
132 | 0 | { |
133 | 0 | if (mbStartingMenu) |
134 | 0 | return true; |
135 | | |
136 | 0 | if (!mpMenu && !mpFloatingWindow) |
137 | 0 | return false; |
138 | | |
139 | 0 | if (mpMenu) |
140 | 0 | return PopupMenu::GetActivePopupMenu() == mpMenu; |
141 | 0 | else |
142 | 0 | { |
143 | 0 | if (mpFloatingWindow->GetType() == WindowType::FLOATINGWINDOW) |
144 | 0 | return static_cast<const FloatingWindow*>(mpFloatingWindow.get())->IsInPopupMode(); |
145 | 0 | else |
146 | 0 | return vcl::Window::GetDockingManager()->IsInPopupMode(mpFloatingWindow); |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | | MenuButton::MenuButton( vcl::Window* pParent, WinBits nWinBits ) |
151 | 0 | : PushButton(WindowType::MENUBUTTON) |
152 | 0 | , mnCurItemId(0) |
153 | 0 | , mbStartingMenu(false) |
154 | 0 | { |
155 | 0 | mnDDStyle = PushButtonDropdownStyle::MenuButton; |
156 | 0 | ImplInit(pParent, nWinBits); |
157 | 0 | } Unexecuted instantiation: MenuButton::MenuButton(vcl::Window*, long) Unexecuted instantiation: MenuButton::MenuButton(vcl::Window*, long) |
158 | | |
159 | | MenuButton::~MenuButton() |
160 | 0 | { |
161 | 0 | disposeOnce(); |
162 | 0 | } |
163 | | |
164 | | void MenuButton::dispose() |
165 | 0 | { |
166 | 0 | mpFloatingWindow.reset(); |
167 | 0 | if (mpMenu && mbOwnPopupMenu) |
168 | 0 | mpMenu->dispose(); |
169 | 0 | mpMenu.reset(); |
170 | 0 | PushButton::dispose(); |
171 | 0 | } |
172 | | |
173 | | void MenuButton::MouseButtonDown( const MouseEvent& rMEvt ) |
174 | 0 | { |
175 | 0 | if ( PushButton::ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) ) |
176 | 0 | { |
177 | 0 | if ( !(GetStyle() & WB_NOPOINTERFOCUS) ) |
178 | 0 | GrabFocus(); |
179 | 0 | ExecuteMenu(); |
180 | 0 | } |
181 | 0 | } |
182 | | |
183 | | void MenuButton::KeyInput( const KeyEvent& rKEvt ) |
184 | 0 | { |
185 | 0 | vcl::KeyCode aKeyCode = rKEvt.GetKeyCode(); |
186 | 0 | sal_uInt16 nCode = aKeyCode.GetCode(); |
187 | 0 | if ( (nCode == KEY_DOWN) && aKeyCode.IsMod2() ) |
188 | 0 | ExecuteMenu(); |
189 | 0 | else if ( !aKeyCode.GetModifier() && |
190 | 0 | ((nCode == KEY_RETURN) || (nCode == KEY_SPACE)) ) |
191 | 0 | ExecuteMenu(); |
192 | 0 | else |
193 | 0 | PushButton::KeyInput( rKEvt ); |
194 | 0 | } |
195 | | |
196 | | void MenuButton::Activate() |
197 | 0 | { |
198 | 0 | maActivateHdl.Call( this ); |
199 | 0 | } |
200 | | |
201 | | void MenuButton::Select() |
202 | 0 | { |
203 | 0 | if (mnCurItemId) |
204 | 0 | collectUIInformation(get_id(),u"OPENFROMLIST"_ustr,u"POS"_ustr,OUString::number(mnCurItemId)); |
205 | |
|
206 | 0 | maSelectHdl.Call( this ); |
207 | 0 | } |
208 | | |
209 | | void MenuButton::SetPopupMenu(PopupMenu* pNewMenu, bool bTakeOwnership) |
210 | 0 | { |
211 | 0 | if (pNewMenu == mpMenu) |
212 | 0 | return; |
213 | | |
214 | 0 | if (mpMenu && mbOwnPopupMenu) |
215 | 0 | mpMenu->dispose(); |
216 | |
|
217 | 0 | mpMenu = pNewMenu; |
218 | 0 | mbOwnPopupMenu = bTakeOwnership; |
219 | 0 | } |
220 | | |
221 | | void MenuButton::SetPopover(Window* pWindow) |
222 | 0 | { |
223 | 0 | if (pWindow == mpFloatingWindow) |
224 | 0 | return; |
225 | | |
226 | 0 | mpFloatingWindow = pWindow; |
227 | 0 | } |
228 | | |
229 | | |
230 | | FactoryFunction MenuButton::GetUITestFactory() const |
231 | 0 | { |
232 | 0 | return MenuButtonUIObject::create; |
233 | 0 | } |
234 | | |
235 | 0 | void MenuButton::SetCurItemId(){ |
236 | 0 | mnCurItemId = mpMenu->GetCurItemId(); |
237 | 0 | msCurItemIdent = mpMenu->GetCurItemIdent(); |
238 | 0 | } |
239 | | |
240 | | void MenuButton::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) |
241 | 0 | { |
242 | 0 | PushButton::DumpAsPropertyTree(rJsonWriter); |
243 | |
|
244 | 0 | if (mpMenu) |
245 | 0 | { |
246 | 0 | auto aMenuNode = rJsonWriter.startArray("menu"); |
247 | 0 | for (int i = 0; i < mpMenu->GetItemCount(); i++) |
248 | 0 | { |
249 | 0 | auto aEntryNode = rJsonWriter.startStruct(); |
250 | 0 | auto sId = mpMenu->GetItemId(i); |
251 | 0 | rJsonWriter.put("id", mpMenu->GetItemIdent(sId)); |
252 | 0 | rJsonWriter.put("text", mpMenu->GetItemText(sId)); |
253 | 0 | } |
254 | 0 | } |
255 | 0 | } |
256 | | |
257 | | //class MenuToggleButton ---------------------------------------------------- |
258 | | |
259 | | MenuToggleButton::MenuToggleButton( vcl::Window* pParent, WinBits nWinBits ) |
260 | 0 | : MenuButton( pParent, nWinBits ) |
261 | 0 | { |
262 | 0 | } Unexecuted instantiation: MenuToggleButton::MenuToggleButton(vcl::Window*, long) Unexecuted instantiation: MenuToggleButton::MenuToggleButton(vcl::Window*, long) |
263 | | |
264 | | MenuToggleButton::~MenuToggleButton() |
265 | 0 | { |
266 | 0 | disposeOnce(); |
267 | 0 | } |
268 | | |
269 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |