32#include <rtl/math.hxx>
35#include <LibreOfficeKit/LibreOfficeKitEnums.h>
39#include <document.hxx>
43using ::com::sun::star::uno::Reference;
51 : maTimer(
"sc SubMenuItemData maTimer")
90 if (!rMenu.mxSubMenuWin)
129 mxMenu->append_text(rText);
130 mxMenu->set_image(
mxMenu->n_children() - 1, css::uno::Reference<css::graphic::XGraphic>(), 1);
156 std::vector<int> aWidths
160 mxMenu->set_column_fixed_widths(aWidths);
177 if (aBackgroundColor.
IsDark())
182 int nWidth = (
mxMenu->get_text_height() * 3) / 4;
186 SymbolType::SPIN_RIGHT, aSpinColor,
187 DrawSymbolFlags::NONE);
199 mxMenu->append_text(rText);
353 if (!rMEvt.IsEnterWindow())
383 for (
auto& aField: aFields)
434 for (
size_t i = 0;
i <
n; ++
i)
467 mxPopover->popup_at_rect(pParent, rRect);
477 mbAllowEmptySet(true), mbRTL(false)
484 , mbHiddenByOtherFilter(false)
488 , meDatePartType(YEAR)
500 bool bHasDates,
int nWidth,
bool bIsMultiField)
501 : mxBuilder(
Application::CreateBuilder(pParent,
"modules/scalc/ui/filterdropdown.ui"))
502 , mxPopover(mxBuilder->weld_popover(
"FilterDropDown"))
503 ,
mxContainer(mxBuilder->weld_container(
"container"))
504 , mxMenu(mxBuilder->weld_tree_view(
"menu"))
505 , mxScratchIter(mxMenu->make_iterator())
506 , mxNonMenu(mxBuilder->weld_widget(
"nonmenu"))
507 , mxFieldsComboLabel(mxBuilder->weld_label(
"select_field_label"))
508 , mxFieldsCombo(mxBuilder->weld_combo_box(
"multi_field_combo"))
509 , mxEdSearch(mxBuilder->weld_entry(
"search_edit"))
510 , mxBox(mxBuilder->weld_widget(
"box"))
511 , mxListChecks(mxBuilder->weld_tree_view(
"check_list_box"))
512 , mxTreeChecks(mxBuilder->weld_tree_view(
"check_tree_box"))
513 , mxChkToggleAll(mxBuilder->weld_check_button(
"toggle_all"))
514 , mxBtnSelectSingle(mxBuilder->weld_button(
"select_current"))
515 , mxBtnUnselectSingle(mxBuilder->weld_button(
"unselect_current"))
516 , mxButtonBox(mxBuilder->weld_box(
"buttonbox"))
517 , mxBtnOk(mxBuilder->weld_button(
"ok"))
518 , mxBtnCancel(mxBuilder->weld_button(
"cancel"))
519 , mxContextMenu(mxBuilder->weld_menu(
"contextmenu"))
520 , mxDropDown(mxMenu->create_virtual_device())
521 , mnCheckWidthReq(-1)
525 , mnSelectedMenu(MENU_NOT_SELECTED)
526 , mrViewData(rViewData)
527 , mnAsyncPostPopdownId(nullptr)
528 , mnAsyncSetDropdownPosId(nullptr)
529 , mbHasDates(bHasDates)
530 , mbIsPoppedUp(false)
533 , maSearchEditTimer(
"ScCheckListMenuControl maSearchEditTimer")
534 , mbIsMultiField(bIsMultiField)
658 rMenuItem.mxSubMenuWin.reset();
664 mxMenu->set_size_request(-1,
mxMenu->get_preferred_size().Height() + 2);
701 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
704 mxContextMenu->set_sensitive(
"less", mnCheckListVisibleRows > 4);
705 mxContextMenu->set_sensitive(
"more", mnCheckListVisibleRows < 42);
707 OUString sCommand = mxContextMenu->popup_at_rect(mpChecks,
tools::Rectangle(rCEvt.GetMousePosPixel(),
Size(1,1)));
708 if (sCommand.isEmpty())
711 if (sCommand ==
"more")
712 ++mnCheckListVisibleRows;
713 else if (sCommand ==
"less")
714 --mnCheckListVisibleRows;
730 if (&rBtn == mxBtnOk.get())
732 else if (&rBtn == mxBtnCancel.get())
734 else if (&rBtn == mxBtnSelectSingle.get() || &rBtn == mxBtnUnselectSingle.get())
736 std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator();
737 bool bEntry = mpChecks->get_cursor(xEntry.get());
740 if (bEntry && mpChecks->get_sensitive(*xEntry, 0))
742 selectCurrentMemberOnly(&rBtn == mxBtnSelectSingle.get());
750 switch (mePrevToggleAllState)
754 setAllMemberState(
true);
758 setAllMemberState(
false);
763 setAllMemberState(
true);
767 mePrevToggleAllState = mxChkToggleAll->get_state();
777 rView.
set_toggle(rIter, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
785 if (mbIsMultiField && mxFieldChangedAction)
786 mxFieldChangedAction->execute();
791 OUString aSearchText = mxEdSearch->get_text();
793 bool bSearchTextEmpty = aSearchText.isEmpty();
794 size_t nEnableMember = std::count_if(maMembers.begin(), maMembers.end(),
796 size_t nSelCount = 0;
804 bool bSomeDateDeletes =
false;
806 for (
size_t i = 0;
i < nEnableMember; ++
i)
808 bool bIsDate = maMembers[
i].mbDate;
809 bool bPartialMatch =
false;
811 OUString aLabelDisp = maMembers[
i].maName;
812 if ( aLabelDisp.isEmpty() )
813 aLabelDisp =
ScResId( STR_EMPTYDATA );
815 if ( !bSearchTextEmpty )
821 maMembers[
i].maRealName + maMembers[
i].maDateParts[1] )).indexOf( aSearchText ) != -1);
828 if ( bSearchTextEmpty )
830 auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[
i],
true, maMembers[
i].
mbVisible);
831 updateMemberParents(xLeaf.get(),
i);
839 auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[
i]);
840 updateMemberParents(xLeaf.get(),
i);
845 ShowCheckEntry(aLabelDisp, maMembers[
i],
false,
false);
847 bSomeDateDeletes =
true;
851 if ( bSomeDateDeletes )
853 for (
size_t i = 0;
i < nEnableMember; ++
i)
855 if (!maMembers[
i].mbDate)
859 updateMemberParents(
nullptr,
i);
875 if (bSearchTextEmpty)
876 nSelCount = initMembers();
879 std::vector<size_t> aShownIndexes;
881 for (
size_t i = 0;
i < nEnableMember; ++
i)
883 assert(!maMembers[
i].mbDate);
885 OUString aLabelDisp = maMembers[
i].maName;
886 if ( aLabelDisp.isEmpty() )
887 aLabelDisp =
ScResId( STR_EMPTYDATA );
894 aShownIndexes.push_back(
i);
897 std::vector<int> aFixedWidths { mnCheckWidthReq };
899 mpChecks->bulk_insert_for_each(aShownIndexes.size(), [
this, &aShownIndexes, &nSelCount](
weld::TreeIter& rIter,
int i) {
900 size_t nIndex = aShownIndexes[i];
901 insertMember(*mpChecks, rIter, maMembers[nIndex], true);
903 },
nullptr, &aFixedWidths);
907 if ( nSelCount == nEnableMember )
909 else if ( nSelCount == 0 )
914 if ( !maConfig.mbAllowEmptySet )
916 const bool bEmptySet( nSelCount == 0 );
917 mpChecks->set_sensitive(!bEmptySet);
918 mxChkToggleAll->set_sensitive(!bEmptySet);
919 mxBtnSelectSingle->set_sensitive(!bEmptySet);
920 mxBtnUnselectSingle->set_sensitive(!bEmptySet);
921 mxBtnOk->set_sensitive(!bEmptySet);
927 maSearchEditTimer.Start();
932 if (mxBtnOk->get_sensitive())
939 Check(&rRowCol.first);
949 if (nNumChecked == nEnableMember)
952 else if (nNumChecked == 0)
960 mxBtnOk->set_sensitive(nNumChecked != 0);
970 OUString aYearName =
maMembers[nIdx].maDateParts[0];
971 OUString aMonthName =
maMembers[nIdx].maDateParts[1];
976 std::unique_ptr<weld::TreeIter> xYearEntry;
987 maMembers[nIdx].mxParent = std::move(xMonthEntry);
990 size_t nMonthIdx = aItr->second;
991 maMembers[nMonthIdx].mxParent = std::move(xYearEntry);
996 std::unique_ptr<weld::TreeIter> xYearEntry =
FindEntry(
nullptr, aYearName);
999 size_t nMonthIdx = aItr->second;
1003 else if (xYearEntry && !
FindEntry(xYearEntry.get(), aMonthName))
1019 aDate.
AddDays(rtl::math::approxFloor(nVal));
1021 sal_Int16 nYear = aDate.
GetYear();
1022 sal_uInt16 nMonth = aDate.
GetMonth();
1023 sal_uInt16 nDay = aDate.
GetDay();
1027 uno::Sequence<i18n::CalendarItem2> aMonths = rCalendar.
getMonths();
1028 if (aMonths.getLength() < nMonth)
1031 OUString aYearName = OUString::number(nYear);
1032 OUString aMonthName = aMonths[nMonth-1].FullName;
1033 OUString aDayName = OUString::number(nDay);
1035 if ( aDayName.getLength() == 1 )
1036 aDayName =
"0" + aDayName;
1040 std::unique_ptr<weld::TreeIter> xYearEntry =
FindEntry(
nullptr, aYearName);
1044 mpChecks->
insert(
nullptr, -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xYearEntry.get());
1049 aMemYear.
maName = aYearName;
1057 maMembers.emplace_back(std::move(aMemYear));
1060 std::unique_ptr<weld::TreeIter> xMonthEntry =
FindEntry(xYearEntry.get(), aMonthName);
1064 mpChecks->
insert(xYearEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xMonthEntry.get());
1069 aMemMonth.
maName = aMonthName;
1072 aMemMonth.
mbLeaf =
false;
1075 aMemMonth.
mxParent = std::move(xYearEntry);
1077 maMembers.emplace_back(std::move(aMemMonth));
1081 std::unique_ptr<weld::TreeIter> xDayEntry =
FindEntry(xMonthEntry.get(), aDayName);
1085 mpChecks->
insert(xMonthEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xDayEntry.get());
1090 aMemDay.
maName = aDayName;
1099 aMemDay.
mxParent = std::move(xMonthEntry);
1101 maMembers.emplace_back(std::move(aMemDay));
1120 maMembers.emplace_back(std::move(aMember));
1154 if (rLabel.isEmpty())
1169 OUString
aLabel = rLabel;
1181 std::unordered_set<OUString> vResults(0);
1199 std::unique_ptr<weld::TreeIter> xEntry =
FindEntry(pParent,
sName);
1205 std::unique_ptr<weld::TreeIter> xEntry =
FindEntry(pParent,
sName);
1241 bool bChildChecked =
false;
1247 bChildChecked =
true;
1259 std::unique_ptr<weld::TreeIter> xEntry;
1276 mpChecks->
insert(
nullptr, -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xYearEntry.get());
1280 std::unique_ptr<weld::TreeIter> xMonthEntry =
FindEntry(xYearEntry.get(), rMember.
maDateParts[1]);
1284 mpChecks->
insert(xYearEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xMonthEntry.get());
1288 std::unique_ptr<weld::TreeIter> xDayEntry =
FindEntry(xMonthEntry.get(), rMember.
maName);
1292 mpChecks->
insert(xMonthEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xDayEntry.get());
1344 std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator();
1345 bool bEntry = mpChecks->get_cursor(xEntry.get());
1346 if (bEntry && mpChecks->get_sensitive(*xEntry, 0))
1348 bool bOldCheck = mpChecks->get_toggle(*xEntry) ==
TRISTATE_TRUE;
1349 CheckEntry(*xEntry, !bOldCheck);
1350 bool bNewCheck = mpChecks->get_toggle(*xEntry) ==
TRISTATE_TRUE;
1351 if (bOldCheck != bNewCheck)
1352 Check(xEntry.get());
1365 size_t nVisMemCount = 0;
1367 if (nMaxMemberWidth == -1)
1372 std::vector<int> aFixedWidths { nMaxMemberWidth };
1381 },
nullptr, &aFixedWidths);
1388 std::vector<std::unique_ptr<weld::TreeIter>> aExpandRows;
1390 for (
size_t i = 0;
i <
n; ++
i)
1400 aExpandRows.emplace_back(std::move(xDateEntry));
1415 for (
const auto& rRow : aExpandRows)
1419 if (nVisMemCount == nEnableMember)
1425 else if (nVisMemCount == 0)
1440 return nVisMemCount;
1458 for (
size_t i = 0;
i <
n; ++
i)
1479 bool bState = vCheckeds.find(
aLabel.makeStringAndClear()) != vCheckeds.end();
1487 aResult.insert(aResultEntry);
1490 rResult.swap(aResult);
1562 mbIsPoppedUp =
false;
1563 clearSelectedMenuItem();
1564 if (mxPopupEndAction)
1565 mxPopupEndAction->execute();
1567 DropPendingEvents();
1578 int nNewWidth = nMaxTextWidth -
nBorder;
1589 : mxBuilder(
Application::CreateBuilder(pParent,
"modules/scalc/ui/filtersubdropdown.ui"))
1590 , mxPopover(mxBuilder->weld_popover(
"FilterSubDropDown"))
1591 ,
mxContainer(mxBuilder->weld_container(
"container"))
1592 , mxMenu(mxBuilder->weld_tree_view(
"menu"))
1593 , mxBackColorMenu(mxBuilder->weld_tree_view(
"background"))
1594 , mxTextColorMenu(mxBuilder->weld_tree_view(
"textcolor"))
1595 , mxScratchIter(mxMenu->make_iterator())
1596 , mrParentControl(rParentControl)
1597 , mnBackColorMenuPrefHeight(-1)
1598 , mnTextColorMenuPrefHeight(-1)
1599 , mbColorMenu(bColorMenu)
1662 mxMenu->set_size_request(-1,
mxMenu->get_preferred_size().Height());
1666 if (nBackColorMenuPrefHeight == -1)
1667 nBackColorMenuPrefHeight =
mxBackColorMenu->get_preferred_size().Height();
1670 if (nTextColorMenuPrefHeight == -1)
1671 nTextColorMenuPrefHeight =
mxTextColorMenu->get_preferred_size().Height();
1738 bool bConsumed =
false;
1746 mrParentControl.endSubMenu(*
this);
1754 (mxBackColorMenu->has_focus() ? *mxBackColorMenu : *mxTextColorMenu);
1756 bConsumed = RowActivatedHdl(rMenu);
1761 if (mxTextColorMenu->get_visible() &&
1762 mxBackColorMenu->has_focus() &&
1763 mxBackColorMenu->get_selected_index() == mxBackColorMenu->n_children() - 1)
1765 mxBackColorMenu->unselect_all();
1766 mxTextColorMenu->select(0);
1767 mxTextColorMenu->set_cursor(0);
1768 mxTextColorMenu->grab_focus();
1775 if (mxBackColorMenu->get_visible() &&
1776 mxTextColorMenu->has_focus() &&
1777 mxTextColorMenu->get_selected_index() == 0)
1779 mxTextColorMenu->unselect_all();
1780 int nIndex = mxBackColorMenu->n_children() - 1;
1781 mxBackColorMenu->select(
nIndex);
1782 mxBackColorMenu->set_cursor(
nIndex);
1783 mxBackColorMenu->grab_focus();
1795 if (rMenu.get_selected_index() == -1)
1797 if (&rMenu != mxTextColorMenu.get())
1798 mxTextColorMenu->unselect_all();
1800 mxBackColorMenu->unselect_all();
1806 executeMenuItem(weld::fromId<ScCheckListMenuControl::Action*>(rMenu.get_selected_id()));
1816 const bool bClosePopup = pAction->
execute();
unotools::WeakReference< AnimationNode > mxParent
const StyleSettings & GetStyleSettings() const
static OUString GetToolkitName()
static const AllSettings & GetSettings()
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
css::uno::Sequence< css::i18n::CalendarItem2 > getMonths() const
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
void AddDays(sal_Int32 nAddDays)
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
sal_uInt16 GetMonth() const
void DrawSymbol(const tools::Rectangle &rRect, SymbolType eType, const Color &rColor, DrawSymbolFlags nStyle=DrawSymbolFlags::NONE)
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
static SC_DLLPUBLIC const CharClass & getCharClass()
static CalendarWrapper & GetCalendar()
ScDocument & GetDocument() const
constexpr tools::Long Width() const
const Color & GetDarkShadowColor() const
const Color & GetWindowColor() const
const Color & GetLightColor() const
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
virtual void Start(bool bStartTimer=true) override
virtual void Invoke() override
reference_type * get() const
sal_uInt16 GetCode() const
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const=0
virtual void expand_row(const TreeIter &rIter)=0
void connect_row_activated(const Link< TreeView &, bool > &rLink)
virtual void set_text(int row, const OUString &rText, int col=-1)=0
virtual OUString get_text(int row, int col=-1) const=0
virtual void set_toggle(int row, TriState eState, int col=-1)=0
virtual int n_children() const=0
virtual void insert(const TreeIter *pParent, int pos, const OUString *pStr, const OUString *pId, const OUString *pIconName, VirtualDevice *pImageSurface, bool bChildrenOnDemand, TreeIter *pRet)=0
std::pair< const TreeIter &, int > iter_col
virtual void set_image(int row, const OUString &rImage, int col=-1)=0
virtual bool get_iter_first(TreeIter &rIter) const=0
void append(TreeIter *pRet=nullptr)
virtual int get_height_rows(int nRows) const=0
virtual void remove(int pos)=0
virtual bool iter_next_sibling(TreeIter &rIter) const=0
virtual bool get_sensitive(int row, int col) const=0
virtual void select(int pos)=0
virtual bool iter_parent(TreeIter &rIter) const=0
virtual bool iter_children(TreeIter &rIter) const=0
virtual TriState get_toggle(int row, int col=-1) const=0
virtual bool iter_has_child(const TreeIter &rIter) const=0
virtual void bulk_insert_for_each(int nSourceCount, const std::function< void(TreeIter &, int nSourceIndex)> &func, const weld::TreeIter *pParent=nullptr, const std::vector< int > *pFixedWidths=nullptr)=0
virtual bool get_cursor(TreeIter *pIter) const=0
virtual void set_cursor(int pos)=0
virtual int get_iter_depth(const TreeIter &rIter) const=0
virtual void all_foreach(const std::function< bool(TreeIter &)> &func)=0
virtual void set_sensitive(int row, bool bSensitive, int col=-1)=0
RegionData_Impl * mpParent
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_LEFT
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_RIGHT
constexpr sal_uInt16 KEY_DOWN
constexpr sal_uInt16 KEY_SPACE
#define LINK(Instance, Class, Member)
tools::Long const nBorder
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
OUString toId(const void *pValue)
OUString ScResId(TranslateId aId)
std::vector< OUString > maDateParts
bool mbHiddenByOtherFilter
DatePartType meDatePartType
std::unique_ptr< weld::TreeIter > mxParent
#define EDIT_UPDATEDATA_TIMEOUT