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/.
12 #include <vcl/timer.hxx>
13 #include <vcl/virdev.hxx>
14 #include <vcl/weld.hxx>
17 #include <unordered_set>
21 class ScCheckListMenuControl
;
23 struct ScCheckListMember
;
26 struct ScCheckListMember
35 OUString maName
; // node name
37 double mnValue
; // number value of filter condition
41 bool mbHiddenByOtherFilter
;
44 bool mbValue
; // true if the filter condition is value
45 DatePartType meDatePartType
;
46 // To store Year and Month if the member if DAY type
47 std::vector
<OUString
> maDateParts
;
49 std::unique_ptr
<weld::TreeIter
> mxParent
;
52 class ScCheckListMenuWindow
;
53 class ScListSubMenuControl
;
56 * This class implements a popup window for the auto filter dropdown.
58 class ScCheckListMenuControl final
61 static constexpr size_t MENU_NOT_SELECTED
= 999;
64 * Action to perform when an event takes place. Create a sub-class of
65 * this to implement the desired action.
71 // return true to dismiss the popup
72 virtual bool execute() = 0;
78 double nValue
; // number value of filter condition
81 bool bValue
; // true if the filter condition is value
83 bool operator<(const ResultEntry
& rhs
) const
85 return aName
< rhs
.aName
;
88 bool operator == (const ResultEntry
& rhs
) const
90 return aName
== rhs
.aName
&&
91 bValid
== rhs
.bValid
&&
93 bValue
== rhs
.bValue
&&
97 typedef std::set
<ResultEntry
> ResultType
;
114 std::shared_ptr
<Action
> mxAction
;
115 std::unique_ptr
<ScListSubMenuControl
> mxSubMenuWin
;
121 * Extended data that the client code may need to store. Create a
122 * sub-class of this and store data there.
124 struct ExtendedData
{
126 virtual ~ExtendedData() {}
131 * Configuration options for this popup window.
135 bool mbAllowEmptySet
;
140 ScCheckListMenuControl(weld::Widget
* pParent
, ScViewData
& rViewData
,
141 bool bTreeMode
, int nWidth
, bool bIsMultiField
= false);
142 ~ScCheckListMenuControl();
144 void addMenuItem(const OUString
& rText
, Action
* pAction
);
146 ScListSubMenuControl
* addSubMenuItem(const OUString
& rText
, bool bEnabled
, bool bColorMenu
);
148 void selectMenuItem(size_t nPos
, bool bSubMenuTimer
);
149 void queueLaunchSubMenu(size_t nPos
, ScListSubMenuControl
* pMenu
);
151 void setMemberSize(size_t n
);
152 void addDateMember(const OUString
& rName
, double nVal
, bool bVisible
, bool bHiddenByOtherFilter
);
153 void addMember(const OUString
& rName
, const double nVal
, bool bVisible
, bool bHiddenByOtherFilter
,
154 bool bValue
= false);
156 size_t initMembers(int nMaxMemberWidth
= -1, bool bUnlock
=false);
157 void setConfig(const Config
& rConfig
);
159 bool isAllSelected() const;
160 void getResult(ResultType
& rResult
);
161 void launch(weld::Widget
* pWidget
, const tools::Rectangle
& rRect
);
162 void close(bool bOK
);
164 void StartPopupMode(weld::Widget
* pParent
, const tools::Rectangle
& rRect
);
167 size_t getSubMenuPos(const ScListSubMenuControl
* pSubMenu
);
168 void setSubMenuFocused(const ScListSubMenuControl
* pSubMenu
);
169 void queueCloseSubMenu();
170 void clearSelectedMenuItem();
173 * Set auxiliary data that the client code might need. Note that this
174 * popup window class manages its life time; no explicit deletion of the
175 * instance is needed in the client code.
177 void setExtendedData(std::unique_ptr
<ExtendedData
> p
);
180 * Get the store auxiliary data, or NULL if no such data is stored.
182 ExtendedData
* getExtendedData();
184 ScViewData
& GetViewData() const { return mrViewData
; }
188 void setOKAction(Action
* p
);
189 void setPopupEndAction(Action
* p
);
190 void setFieldChangedAction(Action
* p
);
192 int GetTextWidth(const OUString
& rsName
) const;
193 int IncreaseWindowWidthToFitText(int nMaxTextWidth
);
196 * Dismiss all visible popup menus and set focus back to the application
197 * window. This method is called e.g. when a menu action is fired.
199 void terminateAllPopupMenus();
201 void endSubMenu(ScListSubMenuControl
& rSubMenu
);
203 void addFields(const std::vector
<OUString
>& aFields
);
204 tools::Long
getField();
206 void SetRestoreFocus(RestoreFocus eFocus
)
208 meRestoreFocus
= eFocus
;
212 std::vector
<MenuItemData
> maMenuItems
;
215 * Calculate the appropriate window size based on the menu items.
218 void setAllMemberState(bool bSet
);
219 void selectCurrentMemberOnly(bool bSet
);
220 void updateMemberParents(const weld::TreeIter
* pLeaf
, size_t nIdx
);
222 std::unique_ptr
<weld::TreeIter
> ShowCheckEntry(const OUString
& sName
, ScCheckListMember
& rMember
, bool bShow
= true, bool bCheck
= true);
223 void CheckEntry(std::u16string_view sName
, const weld::TreeIter
* pParent
, bool bCheck
);
224 void CheckEntry(const weld::TreeIter
& rEntry
, bool bCheck
);
225 void GetRecursiveChecked(const weld::TreeIter
* pEntry
, std::unordered_set
<OUString
>& vOut
, OUString
& rLabel
);
226 std::unordered_set
<OUString
> GetAllChecked();
227 bool IsChecked(std::u16string_view sName
, const weld::TreeIter
* pParent
);
228 int GetCheckedEntryCount() const;
229 void CheckAllChildren(const weld::TreeIter
& rEntry
, bool bCheck
);
231 void setSelectedMenuItem(size_t nPos
);
233 std::unique_ptr
<weld::TreeIter
> FindEntry(const weld::TreeIter
* pParent
, std::u16string_view sNode
);
235 void executeMenuItem(size_t nPos
);
238 * Get the area of the active row. Suitable as the parent rectangle
239 * argument for Executing a popup
241 tools::Rectangle
GetSubMenuParentRect();
243 struct SubMenuItemData
;
245 void handleMenuTimeout(const SubMenuItemData
* pTimer
);
247 void launchSubMenu();
249 void CreateDropDown();
251 DECL_LINK(ButtonHdl
, weld::Button
&, void);
252 DECL_LINK(TriStateHdl
, weld::Toggleable
&, void);
253 DECL_LINK(LockCheckedHdl
, weld::Toggleable
&, void);
255 void Check(const weld::TreeIter
* pIter
);
257 DECL_LINK(CheckHdl
, const weld::TreeView::iter_col
&, void);
259 DECL_LINK(PopupModeEndHdl
, weld::Popover
&, void);
261 DECL_LINK(SearchEditTimeoutHdl
, Timer
*, void);
262 DECL_LINK(ComboChangedHdl
, weld::ComboBox
&, void);
264 DECL_LINK(EdModifyHdl
, weld::Entry
&, void);
265 DECL_LINK(EdActivateHdl
, weld::Entry
&, bool);
267 DECL_LINK(RowActivatedHdl
, weld::TreeView
& rMEvt
, bool);
268 DECL_LINK(SelectHdl
, weld::TreeView
&, void);
269 DECL_LINK(TreeSizeAllocHdl
, const Size
&, void);
270 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
271 DECL_LINK(MenuKeyInputHdl
, const KeyEvent
&, bool);
272 DECL_LINK(MouseEnterHdl
, const MouseEvent
&, bool);
274 DECL_LINK(PostPopdownHdl
, void*, void);
276 void SetDropdownPos();
278 DECL_LINK(SetDropdownPosHdl
, void*, void);
280 DECL_LINK(CommandHdl
, const CommandEvent
&, bool);
282 void ResizeToRequest();
284 void DropPendingEvents();
286 RestoreFocus
DetermineRestoreFocus() const;
287 void RestorePreviousFocus();
290 std::unique_ptr
<weld::Builder
> mxBuilder
;
291 std::unique_ptr
<weld::Popover
> mxPopover
;
292 std::unique_ptr
<weld::Container
> mxContainer
;
293 std::unique_ptr
<weld::TreeView
> mxMenu
;
294 std::unique_ptr
<weld::TreeIter
> mxScratchIter
;
295 std::unique_ptr
<weld::Widget
> mxNonMenu
;
296 std::unique_ptr
<weld::Label
> mxFieldsComboLabel
;
297 std::unique_ptr
<weld::ComboBox
> mxFieldsCombo
;
298 std::unique_ptr
<weld::Entry
> mxEdSearch
;
299 std::unique_ptr
<weld::Widget
> mxBox
;
300 std::unique_ptr
<weld::TreeView
> mxListChecks
;
301 std::unique_ptr
<weld::TreeView
> mxTreeChecks
;
302 weld::TreeView
* mpChecks
;
304 std::unique_ptr
<weld::CheckButton
> mxChkToggleAll
;
305 std::unique_ptr
<weld::CheckButton
> mxChkLockChecked
;
306 std::unique_ptr
<weld::Button
> mxBtnSelectSingle
;
307 std::unique_ptr
<weld::Button
> mxBtnUnselectSingle
;
309 std::unique_ptr
<weld::Box
> mxButtonBox
;
310 std::unique_ptr
<weld::Button
> mxBtnOk
;
311 std::unique_ptr
<weld::Button
> mxBtnCancel
;
312 std::unique_ptr
<weld::Menu
> mxContextMenu
;
314 ScopedVclPtr
<VirtualDevice
> mxDropDown
;
316 std::vector
<ScCheckListMember
> maMembers
;
318 std::map
<OUString
, size_t> maYearMonthMap
;
320 std::unique_ptr
<ExtendedData
> mxExtendedData
;
321 std::unique_ptr
<Action
> mxOKAction
;
322 std::unique_ptr
<Action
> mxPopupEndAction
;
323 std::unique_ptr
<Action
> mxFieldChangedAction
;
326 Size maAllocatedSize
;
327 int mnCheckWidthReq
; /// matching width request for mxChecks
328 int mnWndWidth
; /// whole window width.
329 int mnCheckListVisibleRows
;
330 TriState mePrevToggleAllState
;
332 size_t mnSelectedMenu
;
334 ScViewData
& mrViewData
;
336 ImplSVEvent
* mnAsyncPostPopdownId
;
337 ImplSVEvent
* mnAsyncSetDropdownPosId
;
339 RestoreFocus meRestoreFocus
;
344 struct SubMenuItemData
347 ScListSubMenuControl
* mpSubMenu
;
350 DECL_LINK( TimeoutHdl
, Timer
*, void );
352 SubMenuItemData(ScCheckListMenuControl
* pParent
);
356 ScCheckListMenuControl
* mpParent
;
359 SubMenuItemData maOpenTimer
;
360 SubMenuItemData maCloseTimer
;
362 Timer maSearchEditTimer
;
366 class ScListSubMenuControl final
369 ScListSubMenuControl(weld::Widget
* pParent
, ScCheckListMenuControl
& rParentControl
, bool bColorMenu
);
371 void setPopupStartAction(ScCheckListMenuControl::Action
* p
);
374 bool IsVisible() const;
376 void StartPopupMode(weld::Widget
* pParent
, const tools::Rectangle
& rRect
);
379 void addMenuItem(const OUString
& rText
, ScCheckListMenuControl::Action
* pAction
);
380 // nMenu of 0 for background color, nMenu of 1 for text color
381 void addMenuColorItem(const OUString
& rText
, bool bActive
, VirtualDevice
& rImage
,
382 int nMenu
, ScCheckListMenuControl::Action
* pAction
);
384 void clearMenuItems();
385 void resizeToFitMenuItems();
387 ScViewData
& GetViewData() const { return mrParentControl
.GetViewData(); }
388 ScCheckListMenuControl::ExtendedData
* getExtendedData() { return mrParentControl
.getExtendedData(); }
389 VclPtr
<VirtualDevice
> create_virtual_device() const { return mxMenu
->create_virtual_device(); }
392 * Dismiss all visible popup menus and set focus back to the application
393 * window. This method is called e.g. when a menu action is fired.
395 void terminateAllPopupMenus();
398 std::unique_ptr
<weld::Builder
> mxBuilder
;
399 std::unique_ptr
<weld::Popover
> mxPopover
;
400 std::unique_ptr
<weld::Container
> mxContainer
;
401 std::unique_ptr
<weld::TreeView
> mxMenu
;
402 std::unique_ptr
<weld::TreeView
> mxBackColorMenu
;
403 std::unique_ptr
<weld::TreeView
> mxTextColorMenu
;
404 std::unique_ptr
<weld::TreeIter
> mxScratchIter
;
405 std::unique_ptr
<ScCheckListMenuControl::Action
> mxPopupStartAction
;
406 std::vector
<ScCheckListMenuControl::MenuItemData
> maMenuItems
;
407 ScCheckListMenuControl
& mrParentControl
;
408 int mnBackColorMenuPrefHeight
;
409 int mnTextColorMenuPrefHeight
;
412 DECL_LINK(RowActivatedHdl
, weld::TreeView
& rMEvt
, bool);
413 DECL_LINK(ColorSelChangedHdl
, weld::TreeView
&, void);
414 DECL_LINK(MenuKeyInputHdl
, const KeyEvent
&, bool);
416 void SetupMenu(weld::TreeView
& rMenu
);
418 void executeMenuItem(ScCheckListMenuControl::Action
* pAction
);
419 void addItem(ScCheckListMenuControl::Action
* pAction
);
422 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */