Line data Source code
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 :
10 : #ifndef INCLUDED_SC_SOURCE_UI_INC_CHECKLISTMENU_HXX
11 : #define INCLUDED_SC_SOURCE_UI_INC_CHECKLISTMENU_HXX
12 :
13 : #include <vcl/popupmenuwindow.hxx>
14 : #include <vcl/button.hxx>
15 : #include <vcl/edit.hxx>
16 : #include <vcl/scrbar.hxx>
17 : #include <vcl/timer.hxx>
18 : #include <svx/checklbx.hxx>
19 :
20 : #include <boost/scoped_ptr.hpp>
21 : #include <unordered_map>
22 :
23 : namespace com { namespace sun { namespace star {
24 :
25 : namespace accessibility {
26 : class XAccessible;
27 : }
28 :
29 : }}}
30 :
31 : class ScDocument;
32 : class ScAccessibleFilterMenu;
33 :
34 : class ScMenuFloatingWindow : public PopupMenuFloatingWindow
35 : {
36 : public:
37 : static size_t MENU_NOT_SELECTED;
38 : /**
39 : * Action to perform when an event takes place. Create a sub-class of
40 : * this to implement the desired action.
41 : */
42 0 : class Action
43 : {
44 : public:
45 0 : virtual ~Action() {}
46 : virtual void execute() = 0;
47 : };
48 :
49 : explicit ScMenuFloatingWindow(vcl::Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel = 0);
50 : virtual ~ScMenuFloatingWindow();
51 : void dispose() SAL_OVERRIDE;
52 :
53 : virtual void PopupModeEnd() SAL_OVERRIDE;
54 : virtual void MouseMove(const MouseEvent& rMEvt) SAL_OVERRIDE;
55 : virtual void MouseButtonDown(const MouseEvent& rMEvt) SAL_OVERRIDE;
56 : virtual void MouseButtonUp(const MouseEvent& rMEvt) SAL_OVERRIDE;
57 : virtual void KeyInput(const KeyEvent& rKEvt) SAL_OVERRIDE;
58 : virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
59 : virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() SAL_OVERRIDE;
60 :
61 : void addMenuItem(const OUString& rText, bool bEnabled, Action* pAction);
62 : void addSeparator();
63 :
64 : ScMenuFloatingWindow* addSubMenuItem(const OUString& rText, bool bEnabled);
65 : void setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu);
66 : void selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer);
67 : void clearSelectedMenuItem();
68 : ScMenuFloatingWindow* getSubMenuWindow(size_t nPos) const;
69 : bool isMenuItemSelected(size_t nPos) const;
70 0 : size_t getSelectedMenuItem() const { return mnSelectedMenu;}
71 :
72 : void setName(const OUString& rName);
73 0 : const OUString& getName() const { return maName;}
74 :
75 : void executeMenuItem(size_t nPos);
76 : void getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const;
77 0 : ScMenuFloatingWindow* getParentMenuWindow() const { return mpParentMenu;}
78 :
79 : protected:
80 : virtual void handlePopupEnd();
81 :
82 : Size getMenuSize() const;
83 : void drawMenuItem(vcl::RenderContext& rRenderContext, size_t nPos);
84 : void drawSeparator(vcl::RenderContext& rRenderContext, size_t nPos);
85 : void drawAllMenuItems(vcl::RenderContext& rRenderContext);
86 0 : const vcl::Font& getLabelFont() const
87 : {
88 0 : return maLabelFont;
89 : }
90 :
91 : void queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu);
92 : void queueCloseSubMenu();
93 : void launchSubMenu(bool bSetMenuPos);
94 : void endSubMenu(ScMenuFloatingWindow* pSubMenu);
95 :
96 : void fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const;
97 :
98 0 : ScDocument* getDoc() { return mpDoc;}
99 :
100 : protected:
101 : css::uno::Reference<css::accessibility::XAccessible> mxAccessible;
102 :
103 : private:
104 : struct SubMenuItemData;
105 : void handleMenuTimeout(SubMenuItemData* pTimer);
106 :
107 : void resizeToFitMenuItems();
108 : void highlightMenuItem(vcl::RenderContext& rRenderContext, size_t nPos, bool bSelected);
109 :
110 : size_t getEnclosingMenuItem(const Point& rPos) const;
111 : size_t getSubMenuPos(ScMenuFloatingWindow* pSubMenu);
112 :
113 : /**
114 : * Fire a menu highlight event since the accessibility framework needs
115 : * this to track focus on menu items.
116 : */
117 : void fireMenuHighlightedEvent();
118 :
119 : /**
120 : * Make sure that the specified submenu is permanently up, the submenu
121 : * close timer is not active, and the correct menu item associated with
122 : * the submenu is highlighted.
123 : */
124 : void setSubMenuFocused(ScMenuFloatingWindow* pSubMenu);
125 :
126 : /**
127 : * When a menu item of an invisible submenu is selected, we need to make
128 : * sure that all its parent menu(s) are visible, with the right menu item
129 : * highlighted in each of the parents. Calling this method ensures it.
130 : */
131 : void ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu);
132 :
133 : /**
134 : * Dismiss any visible child submenus when a menu item of a parent menu is
135 : * selected.
136 : */
137 : void ensureSubMenuNotVisible();
138 :
139 : /**
140 : * Dismiss all visible popup menus and set focus back to the application
141 : * window. This method is called e.g. when a menu action is fired.
142 : */
143 : void terminateAllPopupMenus();
144 :
145 : private:
146 :
147 0 : struct MenuItemData
148 : {
149 : OUString maText;
150 : bool mbEnabled:1;
151 : bool mbSeparator:1;
152 :
153 : ::boost::shared_ptr<Action> mpAction;
154 : VclPtr<ScMenuFloatingWindow> mpSubMenuWin;
155 :
156 : MenuItemData();
157 : };
158 :
159 : ::std::vector<MenuItemData> maMenuItems;
160 :
161 0 : struct SubMenuItemData
162 : {
163 : Timer maTimer;
164 : VclPtr<ScMenuFloatingWindow> mpSubMenu;
165 : size_t mnMenuPos;
166 :
167 : DECL_LINK_TYPED( TimeoutHdl, Timer*, void );
168 :
169 : SubMenuItemData(ScMenuFloatingWindow* pParent);
170 : void reset();
171 :
172 : private:
173 : VclPtr<ScMenuFloatingWindow> mpParent;
174 : };
175 : SubMenuItemData maOpenTimer;
176 : SubMenuItemData maCloseTimer;
177 :
178 : vcl::Font maLabelFont;
179 :
180 : // Name of this menu window, taken from the menu item of the parent window
181 : // that launches it (if this is a sub menu). If this is a top-level menu
182 : // window, then this name can be anything.
183 : OUString maName;
184 :
185 : size_t mnSelectedMenu;
186 : size_t mnClickedMenu;
187 :
188 : ScDocument* mpDoc;
189 :
190 : VclPtr<ScMenuFloatingWindow> mpParentMenu;
191 : };
192 :
193 : class ScCheckListBox : public SvTreeListBox
194 : {
195 : SvLBoxButtonData* mpCheckButton;
196 : SvTreeListEntry* CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const;
197 : void CheckAllChildren( SvTreeListEntry* pEntry, bool bCheck = true );
198 :
199 : public:
200 :
201 : ScCheckListBox( vcl::Window* pParent, WinBits nWinStyle = 0 );
202 0 : virtual ~ScCheckListBox() { disposeOnce(); }
203 0 : virtual void dispose() SAL_OVERRIDE { delete mpCheckButton; SvTreeListBox::dispose(); }
204 : void Init();
205 : void CheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bCheck = true );
206 : void CheckEntry( SvTreeListEntry* pEntry, bool bCheck = true );
207 : void ShowCheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bShow = true, bool bCheck = true );
208 : bool IsChecked( const OUString& sName, SvTreeListEntry* pParent );
209 : SvTreeListEntry* FindEntry( SvTreeListEntry* pParent, const OUString& sNode );
210 : sal_uInt16 GetCheckedEntryCount() const;
211 : void ExpandChildren( SvTreeListEntry* pParent );
212 : virtual void KeyInput( const KeyEvent& rKEvt ) SAL_OVERRIDE;
213 : };
214 : /**
215 : * This class implements a popup window for field button, for quick access
216 : * of hide-item list, and possibly more stuff related to field options.
217 : */
218 : class ScCheckListMenuWindow : public ScMenuFloatingWindow
219 : {
220 : public:
221 : typedef std::unordered_map<OUString, bool, OUStringHash> ResultType;
222 :
223 : /**
224 : * Extended data that the client code may need to store. Create a
225 : * sub-class of this and store data there.
226 : */
227 0 : struct ExtendedData {
228 :
229 0 : virtual ~ExtendedData() {}
230 :
231 : };
232 :
233 : /**
234 : * Configuration options for this popup window.
235 : */
236 : struct Config
237 : {
238 : bool mbAllowEmptySet;
239 : bool mbRTL;
240 : Config();
241 : };
242 :
243 : explicit ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc);
244 : virtual ~ScCheckListMenuWindow();
245 : virtual void dispose() SAL_OVERRIDE;
246 :
247 : virtual void MouseMove(const MouseEvent& rMEvt) SAL_OVERRIDE;
248 : virtual bool Notify(NotifyEvent& rNEvt) SAL_OVERRIDE;
249 : virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
250 : virtual vcl::Window* GetPreferredKeyInputWindow() SAL_OVERRIDE;
251 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible() SAL_OVERRIDE;
252 :
253 : void setMemberSize(size_t n);
254 : void addDateMember(const OUString& rName, double nVal, bool bVisible);
255 : void addMember(const OUString& rName, bool bVisible);
256 : void initMembers();
257 : void setConfig(const Config& rConfig);
258 :
259 : bool isAllSelected() const;
260 : void getResult(ResultType& rResult);
261 : void launch(const Rectangle& rRect);
262 : void close(bool bOK);
263 :
264 : /**
265 : * Set auxiliary data that the client code might need. Note that this
266 : * popup window class manages its life time; no explicit deletion of the
267 : * instance is needed in the client code.
268 : */
269 : void setExtendedData(ExtendedData* p);
270 :
271 : /**
272 : * Get the store auxiliary data, or NULL if no such data is stored.
273 : */
274 : ExtendedData* getExtendedData();
275 :
276 : void setOKAction(Action* p);
277 : void setPopupEndAction(Action* p);
278 :
279 : protected:
280 : virtual void handlePopupEnd() SAL_OVERRIDE;
281 :
282 : private:
283 0 : struct Member
284 : {
285 : OUString maName; // node name
286 : OUString maRealName;
287 : bool mbVisible;
288 : bool mbDate;
289 : bool mbLeaf;
290 :
291 : Member();
292 : SvTreeListEntry* mpParent;
293 : };
294 :
295 : class CancelButton : public ::CancelButton
296 : {
297 : public:
298 : CancelButton(ScCheckListMenuWindow* pParent);
299 : virtual ~CancelButton();
300 : virtual void dispose() SAL_OVERRIDE;
301 :
302 : virtual void Click() SAL_OVERRIDE;
303 :
304 : private:
305 : VclPtr<ScCheckListMenuWindow> mpParent;
306 : };
307 :
308 : enum SectionType {
309 : WHOLE, // entire window
310 : LISTBOX_AREA_OUTER, // box enclosing the check box items.
311 : LISTBOX_AREA_INNER, // box enclosing the check box items.
312 : SINGLE_BTN_AREA, // box enclosing the single-action buttons.
313 : CHECK_TOGGLE_ALL, // check box for toggling all items.
314 : BTN_SINGLE_SELECT,
315 : BTN_SINGLE_UNSELECT,
316 : BTN_OK, // OK button
317 : BTN_CANCEL, // Cancel button
318 : EDIT_SEARCH, // Search box
319 : };
320 : void getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const;
321 :
322 : /**
323 : * Calculate the appropriate window size, the position and size of each
324 : * control based on the menu items.
325 : */
326 : void packWindow();
327 : void setAllMemberState(bool bSet);
328 : void selectCurrentMemberOnly(bool bSet);
329 : void cycleFocus(bool bReverse = false);
330 :
331 : DECL_LINK( ButtonHdl, Button* );
332 : DECL_LINK( TriStateHdl, void* );
333 : DECL_LINK( CheckHdl, SvTreeListBox* );
334 : DECL_LINK( EdModifyHdl, void* );
335 :
336 : private:
337 : SvTreeListEntry* findEntry( SvTreeListEntry* pParent, const OUString& rText );
338 :
339 : VclPtr<Edit> maEdSearch;
340 : VclPtr<ScCheckListBox> maChecks;
341 :
342 : VclPtr<TriStateBox> maChkToggleAll;
343 : VclPtr<ImageButton> maBtnSelectSingle;
344 : VclPtr<ImageButton> maBtnUnselectSingle;
345 :
346 : VclPtr<OKButton> maBtnOk;
347 : VclPtr<CancelButton> maBtnCancel;
348 :
349 : ::std::vector<VclPtr<vcl::Window> > maTabStopCtrls;
350 : size_t mnCurTabStop;
351 :
352 : ::std::vector<Member> maMembers;
353 : boost::scoped_ptr<ExtendedData> mpExtendedData;
354 : boost::scoped_ptr<Action> mpOKAction;
355 : boost::scoped_ptr<Action> mpPopupEndAction;
356 :
357 : Config maConfig;
358 : Size maWndSize; /// whole window size.
359 : Size maMenuSize; /// size of all menu items combined.
360 : TriState mePrevToggleAllState;
361 : };
362 :
363 : #endif
364 :
365 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|