23 #include <globstr.hrc>
32 #include <rtl/math.hxx>
35 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
39 #include <document.hxx>
43 using ::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);
172 int nWidth = (
mxMenu->get_text_height() * 3) / 4;
176 SymbolType::SPIN_RIGHT,
mxDropDown->GetTextColor(),
177 DrawSymbolFlags::NONE);
189 mxMenu->append_text(rText);
215 const bool bClosePopup =
maMenuItems[nPos].mxAction->execute();
343 if (!rMEvt.IsEnterWindow())
403 for (
size_t i = 0;
i < n; ++
i)
436 mxPopover->popup_at_rect(pParent, rRect);
446 mbAllowEmptySet(true), mbRTL(
false)
456 , meDatePartType(YEAR)
468 bool bHasDates,
int nWidth)
469 : mxBuilder(
Application::CreateBuilder(pParent,
"modules/scalc/ui/filterdropdown.ui"))
470 , mxPopover(mxBuilder->weld_popover(
"FilterDropDown"))
471 ,
mxContainer(mxBuilder->weld_container(
"container"))
472 , mxMenu(mxBuilder->weld_tree_view(
"menu"))
473 , mxScratchIter(mxMenu->make_iterator())
474 , mxNonMenu(mxBuilder->weld_widget(
"nonmenu"))
475 , mxEdSearch(mxBuilder->weld_entry(
"search_edit"))
476 , mxBox(mxBuilder->weld_widget(
"box"))
477 , mxListChecks(mxBuilder->weld_tree_view(
"check_list_box"))
478 , mxTreeChecks(mxBuilder->weld_tree_view(
"check_tree_box"))
479 , mxChkToggleAll(mxBuilder->weld_check_button(
"toggle_all"))
480 , mxBtnSelectSingle(mxBuilder->weld_button(
"select_current"))
481 , mxBtnUnselectSingle(mxBuilder->weld_button(
"unselect_current"))
482 , mxButtonBox(mxBuilder->weld_box(
"buttonbox"))
483 , mxBtnOk(mxBuilder->weld_button(
"ok"))
484 , mxBtnCancel(mxBuilder->weld_button(
"cancel"))
485 , mxContextMenu(mxBuilder->weld_menu(
"contextmenu"))
486 , mxDropDown(mxMenu->create_virtual_device())
487 , mnCheckWidthReq(-1)
491 , mnSelectedMenu(MENU_NOT_SELECTED)
492 , mrViewData(rViewData)
493 , mnAsyncPostPopdownId(nullptr)
494 , mnAsyncSetDropdownPosId(nullptr)
495 , mbHasDates(bHasDates)
496 , mbIsPoppedUp(
false)
606 rMenuItem.mxSubMenuWin.reset();
612 mxMenu->set_size_request(-1,
mxMenu->get_preferred_size().Height() + 2);
648 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
651 mxContextMenu->set_sensitive(
"less", mnCheckListVisibleRows > 4);
652 mxContextMenu->set_sensitive(
"more", mnCheckListVisibleRows < 42);
654 OString sCommand = mxContextMenu->popup_at_rect(mpChecks,
tools::Rectangle(rCEvt.GetMousePosPixel(),
Size(1,1)));
655 if (sCommand.isEmpty())
658 if (sCommand ==
"more")
659 ++mnCheckListVisibleRows;
660 else if (sCommand ==
"less")
661 --mnCheckListVisibleRows;
677 if (&rBtn == mxBtnOk.get())
679 else if (&rBtn == mxBtnCancel.get())
681 else if (&rBtn == mxBtnSelectSingle.get() || &rBtn == mxBtnUnselectSingle.get())
683 selectCurrentMemberOnly(&rBtn == mxBtnSelectSingle.get());
684 std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator();
685 if (!mpChecks->get_cursor(xEntry.get()))
693 switch (mePrevToggleAllState)
697 setAllMemberState(
true);
701 setAllMemberState(
false);
706 setAllMemberState(
true);
710 mePrevToggleAllState = mxChkToggleAll->get_state();
718 if (aLabel.isEmpty())
719 aLabel =
ScResId(STR_EMPTYDATA);
720 rView.
set_toggle(rIter, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
727 OUString aSearchText = mxEdSearch->get_text();
729 bool bSearchTextEmpty = aSearchText.isEmpty();
730 size_t n = maMembers.size();
731 size_t nSelCount = 0;
739 bool bSomeDateDeletes =
false;
741 for (
size_t i = 0;
i < n; ++
i)
743 bool bIsDate = maMembers[
i].mbDate;
744 bool bPartialMatch =
false;
746 OUString aLabelDisp = maMembers[
i].maName;
747 if ( aLabelDisp.isEmpty() )
748 aLabelDisp =
ScResId( STR_EMPTYDATA );
750 if ( !bSearchTextEmpty )
756 maMembers[
i].maRealName + maMembers[
i].maDateParts[1] )).indexOf( aSearchText ) != -1);
763 if ( bSearchTextEmpty )
765 auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[
i],
true, maMembers[i].
mbVisible);
766 updateMemberParents(xLeaf.get(), i);
767 if ( maMembers[i].mbVisible )
774 auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[
i]);
775 updateMemberParents(xLeaf.get(), i);
780 ShowCheckEntry(aLabelDisp, maMembers[
i],
false,
false);
782 bSomeDateDeletes =
true;
786 if ( bSomeDateDeletes )
788 for (
size_t i = 0;
i < n; ++
i)
790 if (!maMembers[
i].mbDate)
794 updateMemberParents(
nullptr,
i);
810 if (bSearchTextEmpty)
811 nSelCount = initMembers();
814 std::vector<size_t> aShownIndexes;
816 for (
size_t i = 0;
i < n; ++
i)
818 assert(!maMembers[
i].mbDate);
820 OUString aLabelDisp = maMembers[
i].maName;
821 if ( aLabelDisp.isEmpty() )
822 aLabelDisp =
ScResId( STR_EMPTYDATA );
829 aShownIndexes.push_back(
i);
832 std::vector<int> aFixedWidths { mnCheckWidthReq };
834 mpChecks->bulk_insert_for_each(aShownIndexes.size(), [
this, &aShownIndexes, &nSelCount](
weld::TreeIter& rIter,
int i) {
835 size_t nIndex = aShownIndexes[
i];
836 insertMember(*mpChecks, rIter, maMembers[nIndex],
true);
838 },
nullptr, &aFixedWidths);
842 if ( nSelCount == n )
844 else if ( nSelCount == 0 )
849 if ( !maConfig.mbAllowEmptySet )
851 const bool bEmptySet( nSelCount == 0 );
852 mpChecks->set_sensitive(!bEmptySet);
853 mxChkToggleAll->set_sensitive(!bEmptySet);
854 mxBtnSelectSingle->set_sensitive(!bEmptySet);
855 mxBtnUnselectSingle->set_sensitive(!bEmptySet);
856 mxBtnOk->set_sensitive(!bEmptySet);
862 if (mxBtnOk->get_sensitive())
869 Check(&rRowCol.first);
880 else if (nNumChecked == 0)
888 mxBtnOk->set_sensitive(nNumChecked != 0);
898 OUString aYearName =
maMembers[nIdx].maDateParts[0];
899 OUString aMonthName =
maMembers[nIdx].maDateParts[1];
904 std::unique_ptr<weld::TreeIter> xYearEntry;
915 maMembers[nIdx].mxParent = std::move(xMonthEntry);
918 size_t nMonthIdx = aItr->second;
919 maMembers[nMonthIdx].mxParent = std::move(xYearEntry);
924 std::unique_ptr<weld::TreeIter> xYearEntry =
FindEntry(
nullptr, aYearName);
927 size_t nMonthIdx = aItr->second;
931 else if (xYearEntry && !
FindEntry(xYearEntry.get(), aMonthName))
947 aDate.
AddDays(rtl::math::approxFloor(nVal));
949 sal_Int16 nYear = aDate.
GetYear();
950 sal_uInt16 nMonth = aDate.
GetMonth();
951 sal_uInt16 nDay = aDate.
GetDay();
955 uno::Sequence<i18n::CalendarItem2> aMonths = rCalendar.
getMonths();
956 if (aMonths.getLength() < nMonth)
959 OUString aYearName = OUString::number(nYear);
960 OUString aMonthName = aMonths[nMonth-1].FullName;
961 OUString aDayName = OUString::number(nDay);
963 if ( aDayName.getLength() == 1 )
964 aDayName =
"0" + aDayName;
968 std::unique_ptr<weld::TreeIter> xYearEntry =
FindEntry(
nullptr, aYearName);
972 mpChecks->
insert(
nullptr, -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xYearEntry.get());
976 aMemYear.
maName = aYearName;
983 maMembers.emplace_back(std::move(aMemYear));
986 std::unique_ptr<weld::TreeIter> xMonthEntry =
FindEntry(xYearEntry.get(), aMonthName);
990 mpChecks->
insert(xYearEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xMonthEntry.get());
994 aMemMonth.
maName = aMonthName;
999 aMemMonth.
mxParent = std::move(xYearEntry);
1001 maMembers.emplace_back(std::move(aMemMonth));
1005 std::unique_ptr<weld::TreeIter> xDayEntry =
FindEntry(xMonthEntry.get(), aDayName);
1009 mpChecks->
insert(xMonthEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xDayEntry.get());
1013 aMemDay.
maName = aDayName;
1021 aMemDay.
mxParent = std::move(xMonthEntry);
1023 maMembers.emplace_back(std::move(aMemDay));
1041 maMembers.emplace_back(std::move(aMember));
1066 if (rLabel.isEmpty())
1081 OUString aLabel = rLabel;
1083 if (!aLabel.isEmpty() && aLabel != rLabel)
1084 vOut.insert(aLabel);
1093 std::unordered_set<OUString> vResults(0);
1101 if (!aLabel.isEmpty())
1102 vResults.insert(aLabel);
1111 std::unique_ptr<weld::TreeIter> xEntry =
FindEntry(pParent, sName);
1117 std::unique_ptr<weld::TreeIter> xEntry =
FindEntry(pParent, sName);
1153 bool bChildChecked =
false;
1159 bChildChecked =
true;
1171 std::unique_ptr<weld::TreeIter> xEntry;
1188 mpChecks->
insert(
nullptr, -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xYearEntry.get());
1192 std::unique_ptr<weld::TreeIter> xMonthEntry =
FindEntry(xYearEntry.get(), rMember.
maDateParts[1]);
1196 mpChecks->
insert(xYearEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xMonthEntry.get());
1200 std::unique_ptr<weld::TreeIter> xDayEntry =
FindEntry(xMonthEntry.get(), rMember.
maName);
1204 mpChecks->
insert(xMonthEntry.get(), -1,
nullptr,
nullptr,
nullptr,
nullptr,
false, xDayEntry.get());
1256 std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator();
1257 bool bEntry = mpChecks->get_cursor(xEntry.get());
1260 bool bOldCheck = mpChecks->get_toggle(*xEntry) ==
TRISTATE_TRUE;
1261 CheckEntry(*xEntry, !bOldCheck);
1262 bool bNewCheck = mpChecks->get_toggle(*xEntry) ==
TRISTATE_TRUE;
1263 if (bOldCheck != bNewCheck)
1264 Check(xEntry.get());
1275 size_t nVisMemCount = 0;
1277 if (nMaxMemberWidth == -1)
1282 std::vector<int> aFixedWidths { nMaxMemberWidth };
1291 },
nullptr, &aFixedWidths);
1298 std::vector<std::unique_ptr<weld::TreeIter>> aExpandRows;
1300 for (
size_t i = 0;
i < n; ++
i)
1310 aExpandRows.emplace_back(std::move(xDateEntry));
1325 for (
const auto& rRow : aExpandRows)
1329 if (nVisMemCount == n)
1335 else if (nVisMemCount == 0)
1350 return nVisMemCount;
1368 for (
size_t i = 0;
i < n; ++
i)
1373 if (aLabel.isEmpty())
1374 aLabel =
ScResId(STR_EMPTYDATA);
1389 bool bState = vCheckeds.find(aLabel.makeStringAndClear()) != vCheckeds.end();
1392 aResultEntry.
bValid = bState;
1397 aResult.insert(aResultEntry);
1400 rResult.swap(aResult);
1467 mbIsPoppedUp =
false;
1468 clearSelectedMenuItem();
1469 if (mxPopupEndAction)
1470 mxPopupEndAction->execute();
1472 DropPendingEvents();
1483 int nNewWidth = nMaxTextWidth - nBorder;
1494 : mxBuilder(
Application::CreateBuilder(pParent,
"modules/scalc/ui/filtersubdropdown.ui"))
1495 , mxPopover(mxBuilder->weld_popover(
"FilterSubDropDown"))
1496 ,
mxContainer(mxBuilder->weld_container(
"container"))
1497 , mxMenu(mxBuilder->weld_tree_view(
"menu"))
1498 , mxBackColorMenu(mxBuilder->weld_tree_view(
"background"))
1499 , mxTextColorMenu(mxBuilder->weld_tree_view(
"textcolor"))
1500 , mxScratchIter(mxMenu->make_iterator())
1501 , mrParentControl(rParentControl)
1502 , mnBackColorMenuPrefHeight(-1)
1503 , mnTextColorMenuPrefHeight(-1)
1504 , mbColorMenu(bColorMenu)
1567 mxMenu->set_size_request(-1,
mxMenu->get_preferred_size().Height());
1571 if (nBackColorMenuPrefHeight == -1)
1572 nBackColorMenuPrefHeight =
mxBackColorMenu->get_preferred_size().Height();
1575 if (nTextColorMenuPrefHeight == -1)
1576 nTextColorMenuPrefHeight =
mxTextColorMenu->get_preferred_size().Height();
1604 rColorMenu.
insert(
nullptr, -1, &rText, &sId,
nullptr,
nullptr,
false,
mxScratchIter.get());
1643 bool bConsumed =
false;
1651 mrParentControl.endSubMenu(*
this);
1659 (mxBackColorMenu->has_focus() ? *mxBackColorMenu : *mxTextColorMenu);
1661 bConsumed = RowActivatedHdl(rMenu);
1666 if (mxTextColorMenu->get_visible() &&
1667 mxBackColorMenu->has_focus() &&
1668 mxBackColorMenu->get_selected_index() == mxBackColorMenu->n_children() - 1)
1670 mxBackColorMenu->unselect_all();
1671 mxTextColorMenu->select(0);
1672 mxTextColorMenu->set_cursor(0);
1673 mxTextColorMenu->grab_focus();
1680 if (mxBackColorMenu->get_visible() &&
1681 mxTextColorMenu->has_focus() &&
1682 mxTextColorMenu->get_selected_index() == 0)
1684 mxTextColorMenu->unselect_all();
1685 int nIndex = mxBackColorMenu->n_children() - 1;
1686 mxBackColorMenu->select(nIndex);
1687 mxBackColorMenu->set_cursor(nIndex);
1688 mxBackColorMenu->grab_focus();
1700 if (rMenu.get_selected_index() == -1)
1702 if (&rMenu != mxTextColorMenu.get())
1703 mxTextColorMenu->unselect_all();
1705 mxBackColorMenu->unselect_all();
1711 executeMenuItem(weld::fromId<ScCheckListMenuControl::Action*>(rMenu.get_selected_id()));
1721 const bool bClosePopup = pAction->
execute();
virtual void set_text(int row, const OUString &rText, int col=-1)=0
#define LINK(Instance, Class, Member)
OUString ScResId(TranslateId aId)
virtual bool iter_parent(TreeIter &rIter) const =0
std::unique_ptr< weld::TreeIter > mxParent
virtual void insert(const TreeIter *pParent, int pos, const OUString *pStr, const OUString *pId, const OUString *pIconName, VirtualDevice *pImageSurface, bool bChildrenOnDemand, TreeIter *pRet)=0
WeakReference< XInterface > mxParent
static const AllSettings & GetSettings()
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
sal_uInt16 GetCode() const
ScDocument & GetDocument() const
constexpr sal_uInt16 KEY_SPACE
virtual TriState get_toggle(int row, int col=-1) const =0
constexpr sal_uInt16 KEY_UP
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const =0
constexpr tools::Long Width() const
sal_uInt16 GetMonth() const
std::pair< const TreeIter &, int > iter_col
virtual int n_children() const =0
void connect_row_activated(const Link< TreeView &, bool > &rLink)
sal_Int16 GetYear() const
constexpr sal_uInt16 KEY_DOWN
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
std::vector< OUString > maDateParts
virtual void set_toggle(int row, TriState eState, int col=-1)=0
static SC_DLLPUBLIC const CharClass & getCharClass()
virtual bool iter_has_child(const TreeIter &rIter) const =0
static OUString GetToolkitName()
virtual void Start(bool bStartTimer=true) override
sal_uInt16 GetDay() const
virtual void Invoke() override
void AddDays(sal_Int32 nAddDays)
virtual OUString get_text(int row, int col=-1) const =0
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
virtual void expand_row(const TreeIter &rIter)=0
void SetTimeout(sal_uInt64 nTimeoutMs)
DatePartType meDatePartType
virtual bool get_cursor(TreeIter *pIter) const =0
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_RIGHT
virtual bool iter_children(TreeIter &rIter) const =0
virtual void remove(int pos)=0
tools::Long const nBorder
RegionData_Impl * mpParent
OUString toId(const void *pValue)
virtual void select(int pos)=0
virtual void all_foreach(const std::function< bool(TreeIter &)> &func)=0
constexpr sal_uInt16 KEY_ESCAPE
static CalendarWrapper & GetCalendar()
css::uno::Sequence< css::i18n::CalendarItem2 > getMonths() const
std::u16string_view trim(std::u16string_view str)
virtual bool get_iter_first(TreeIter &rIter) const =0
virtual int get_height_rows(int nRows) const =0
virtual void set_cursor(int pos)=0
void SetInvokeHandler(const Link< Timer *, void > &rLink)
void append(TreeIter *pRet=nullptr)
virtual void set_image(int row, const OUString &rImage, int col=-1)=0
VirtualDevice * get() const
virtual bool iter_next_sibling(TreeIter &rIter) const =0
void DrawSymbol(const tools::Rectangle &rRect, SymbolType eType, const Color &rColor, DrawSymbolFlags nStyle=DrawSymbolFlags::NONE)
constexpr sal_uInt16 KEY_LEFT
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 int get_iter_depth(const TreeIter &rIter) const =0
bool m_bDetectedRangeSegmentation false