Resolves: tdf#144811 use the hover-style menu for color submenus
Change-Id: I8653c36d084f9df5a4d34baf7d88e2f2b5f1609b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126209
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index f4caff9..7e0c9fc 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -38,6 +38,8 @@
#include <vcl/jsdialog/executor.hxx>
#include <document.hxx>
#include <docsh.hxx>
#include <viewdata.hxx>
using namespace com::sun::star;
using ::com::sun::star::uno::Reference;
@@ -120,7 +122,7 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, SelectHdl, weld::TreeView&, void)
setSelectedMenuItem(nSelectedMenu, true);
}
void ScCheckListMenuControl::addMenuItem(const OUString& rText, Action* pAction, bool bIndicateSubMenu)
void ScCheckListMenuControl::addMenuItem(const OUString& rText, Action* pAction)
{
MenuItemData aItem;
aItem.mbEnabled = true;
@@ -129,10 +131,7 @@ void ScCheckListMenuControl::addMenuItem(const OUString& rText, Action* pAction,
mxMenu->show();
mxMenu->append_text(rText);
if (bIndicateSubMenu)
mxMenu->set_image(mxMenu->n_children() - 1, *mxDropDown, 1);
else
mxMenu->set_image(mxMenu->n_children() - 1, css::uno::Reference<css::graphic::XGraphic>(), 1);
mxMenu->set_image(mxMenu->n_children() - 1, css::uno::Reference<css::graphic::XGraphic>(), 1);
}
void ScCheckListMenuControl::addSeparator()
@@ -180,12 +179,12 @@ void ScCheckListMenuControl::CreateDropDown()
DrawSymbolFlags::NONE);
}
ScListSubMenuControl* ScCheckListMenuControl::addSubMenuItem(const OUString& rText, bool bEnabled)
ScListSubMenuControl* ScCheckListMenuControl::addSubMenuItem(const OUString& rText, bool bEnabled, bool bCheckList)
{
MenuItemData aItem;
aItem.mbEnabled = bEnabled;
aItem.mxSubMenuWin.reset(new ScListSubMenuControl(mxMenu.get(), *this, mpNotifier));
aItem.mxSubMenuWin.reset(new ScListSubMenuControl(mxMenu.get(), *this, bCheckList, mpNotifier));
maMenuItems.emplace_back(std::move(aItem));
mxMenu->show();
@@ -451,7 +450,7 @@ constexpr int nBorderWidth = 4;
// number of rows visible in checklist
constexpr int nCheckListVisibleRows = 8;
ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScDocument* pDoc,
ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData& rViewData,
bool bHasDates, int nWidth, vcl::ILibreOfficeKitNotifier* pNotifier)
: mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/filterdropdown.ui"))
, mxPopover(mxBuilder->weld_popover("FilterDropDown"))
@@ -474,7 +473,7 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScDocument
, mnWndWidth(0)
, mePrevToggleAllState(TRISTATE_INDET)
, mnSelectedMenu(MENU_NOT_SELECTED)
, mpDoc(pDoc)
, mrViewData(rViewData)
, mnAsyncPostPopdownId(nullptr)
, mnAsyncSetDropdownPosId(nullptr)
, mpNotifier(pNotifier)
@@ -890,7 +889,7 @@ void ScCheckListMenuControl::setMemberSize(size_t n)
void ScCheckListMenuControl::addDateMember(const OUString& rsName, double nVal, bool bVisible)
{
SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
SvNumberFormatter* pFormatter = mrViewData.GetDocument().GetFormatTable();
// Convert the numeric date value to a date object.
Date aDate = pFormatter->GetNullDate();
@@ -1448,7 +1447,7 @@ int ScCheckListMenuControl::IncreaseWindowWidthToFitText(int nMaxTextWidth)
return mnCheckWidthReq + nBorder;
}
ScListSubMenuControl::ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, vcl::ILibreOfficeKitNotifier* pNotifier)
ScListSubMenuControl::ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, bool bCheckList, vcl::ILibreOfficeKitNotifier* pNotifier)
: mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/filtersubdropdown.ui"))
, mxPopover(mxBuilder->weld_popover("FilterSubDropDown"))
, mxContainer(mxBuilder->weld_container("container"))
@@ -1457,12 +1456,22 @@ ScListSubMenuControl::ScListSubMenuControl(weld::Widget* pParent, ScCheckListMen
, mrParentControl(rParentControl)
, mpNotifier(pNotifier)
{
if (bCheckList)
{
mxMenu->set_clicks_to_toggle(1);
mxMenu->enable_toggle_buttons(weld::ColumnToggleType::Radio);
}
mxMenu->connect_row_activated(LINK(this, ScListSubMenuControl, RowActivatedHdl));
mxMenu->connect_toggled(LINK(this, ScListSubMenuControl, CheckToggledHdl));
mxMenu->connect_key_press(LINK(this, ScListSubMenuControl, MenuKeyInputHdl));
}
void ScListSubMenuControl::StartPopupMode(weld::Widget* pParent, const tools::Rectangle& rRect)
{
if (mxPopupStartAction)
mxPopupStartAction->execute();
mxPopover->popup_at_rect(pParent, rRect, weld::Placement::End);
mxMenu->set_cursor(0);
@@ -1491,16 +1500,33 @@ void ScListSubMenuControl::resizeToFitMenuItems()
mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2);
}
void ScListSubMenuControl::addMenuItem(const OUString& rText, ScCheckListMenuControl::Action* pAction)
void ScListSubMenuControl::addItem(ScCheckListMenuControl::Action* pAction)
{
ScCheckListMenuControl::MenuItemData aItem;
aItem.mbEnabled = true;
aItem.mxAction.reset(pAction);
maMenuItems.emplace_back(std::move(aItem));
mxMenu->show();
}
void ScListSubMenuControl::addMenuItem(const OUString& rText, ScCheckListMenuControl::Action* pAction)
{
addItem(pAction);
mxMenu->append_text(rText);
}
void ScListSubMenuControl::addMenuCheckItem(const OUString& rText, bool bActive, VirtualDevice& rImage, ScCheckListMenuControl::Action* pAction)
{
addItem(pAction);
mxMenu->insert(nullptr, -1, &rText, nullptr, nullptr, &rImage, false, mxScratchIter.get());
mxMenu->set_toggle(*mxScratchIter, bActive ? TRISTATE_TRUE : TRISTATE_FALSE);
}
void ScListSubMenuControl::clearMenuItems()
{
maMenuItems.clear();
mxMenu->clear();
}
IMPL_LINK(ScListSubMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool)
{
bool bConsumed = false;
@@ -1515,6 +1541,13 @@ IMPL_LINK(ScListSubMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool)
bConsumed = true;
break;
}
case KEY_SPACE:
case KEY_RETURN:
{
// don't toggle checkbutton, go straight to activating entry
bConsumed = RowActivatedHdl(*mxMenu);
break;
}
}
return bConsumed;
@@ -1526,6 +1559,16 @@ IMPL_LINK_NOARG(ScListSubMenuControl, RowActivatedHdl, weld::TreeView&, bool)
return true;
}
IMPL_LINK(ScListSubMenuControl, CheckToggledHdl, const weld::TreeView::iter_col&, rRowCol, void)
{
mxMenu->all_foreach([this, &rRowCol](weld::TreeIter& rEntry){
bool bToggledEntry = mxMenu->iter_compare(rEntry, rRowCol.first) == 0;
if (!bToggledEntry)
mxMenu->set_toggle(rEntry, TRISTATE_FALSE);
return false;
});
}
void ScListSubMenuControl::executeMenuItem(size_t nPos)
{
if (nPos >= maMenuItems.size())
@@ -1540,6 +1583,11 @@ void ScListSubMenuControl::executeMenuItem(size_t nPos)
terminateAllPopupMenus();
}
void ScListSubMenuControl::setPopupStartAction(ScCheckListMenuControl::Action* p)
{
mxPopupStartAction.reset(p);
}
void ScListSubMenuControl::terminateAllPopupMenus()
{
if (comphelper::LibreOfficeKit::isActive())
diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx
index 6a5dbce..961fddc 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -11,6 +11,7 @@
#include <vcl/dockwin.hxx>
#include <vcl/timer.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <memory>
@@ -18,10 +19,8 @@
#include <map>
#include <set>
class ScDocument;
class ScCheckListMenuControl;
class ScViewData;
struct ScCheckListMember;
struct ScCheckListMember
@@ -123,14 +122,14 @@ public:
Config();
};
ScCheckListMenuControl(weld::Widget* pParent, ScDocument* pDoc,
ScCheckListMenuControl(weld::Widget* pParent, ScViewData& rViewData,
bool bTreeMode, int nWidth,
vcl::ILibreOfficeKitNotifier* pNotifier);
~ScCheckListMenuControl();
void addMenuItem(const OUString& rText, Action* pAction, bool bIndicateSubMenu = false);
void addMenuItem(const OUString& rText, Action* pAction);
void addSeparator();
ScListSubMenuControl* addSubMenuItem(const OUString& rText, bool bEnabled);
ScListSubMenuControl* addSubMenuItem(const OUString& rText, bool bEnabled, bool bCheckList);
void resizeToFitMenuItems();
void selectMenuItem(size_t nPos, bool bSubMenuTimer);
@@ -168,6 +167,8 @@ public:
*/
ExtendedData* getExtendedData();
ScViewData& GetViewData() const { return mrViewData; }
void GrabFocus();
void setOKAction(Action* p);
@@ -292,7 +293,7 @@ private:
size_t mnSelectedMenu;
ScDocument* mpDoc;
ScViewData& mrViewData;
ImplSVEvent* mnAsyncPostPopdownId;
ImplSVEvent* mnAsyncSetDropdownPosId;
@@ -323,7 +324,9 @@ private:
class ScListSubMenuControl final
{
public:
ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, vcl::ILibreOfficeKitNotifier* pNotifier);
ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, bool bCheckList, vcl::ILibreOfficeKitNotifier* pNotifier);
void setPopupStartAction(ScCheckListMenuControl::Action* p);
void GrabFocus();
bool IsVisible() const;
@@ -332,10 +335,16 @@ public:
void EndPopupMode();
void addMenuItem(const OUString& rText, ScCheckListMenuControl::Action* pAction);
void addMenuCheckItem(const OUString& rText, bool bActive, VirtualDevice& rImage, ScCheckListMenuControl::Action* pAction);
void clearMenuItems();
void resizeToFitMenuItems();
void setSelectedMenuItem(size_t nPos);
ScViewData& GetViewData() const { return mrParentControl.GetViewData(); }
ScCheckListMenuControl::ExtendedData* getExtendedData() { return mrParentControl.getExtendedData(); }
VclPtr<VirtualDevice> create_virtual_device() const { return mxMenu->create_virtual_device(); }
/**
* Dismiss all visible popup menus and set focus back to the application
* window. This method is called e.g. when a menu action is fired.
@@ -348,15 +357,18 @@ private:
std::unique_ptr<weld::Container> mxContainer;
std::unique_ptr<weld::TreeView> mxMenu;
std::unique_ptr<weld::TreeIter> mxScratchIter;
std::unique_ptr<ScCheckListMenuControl::Action> mxPopupStartAction;
std::vector<ScCheckListMenuControl::MenuItemData> maMenuItems;
ScCheckListMenuControl& mrParentControl;
vcl::ILibreOfficeKitNotifier* mpNotifier;
DECL_LINK(RowActivatedHdl, weld::TreeView& rMEvt, bool);
DECL_LINK(CheckToggledHdl, const weld::TreeView::iter_col&, void);
DECL_LINK(MenuKeyInputHdl, const KeyEvent&, bool);
void NotifyCloseLOK();
void executeMenuItem(size_t nPos);
void addItem(ScCheckListMenuControl::Action* pAction);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 81be888..dd24eb94 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -24,12 +24,13 @@
#include <editeng/adjustitem.hxx>
#include <sot/storage.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/editview.hxx>
#include <editeng/editobj.hxx>
#include <editeng/editstat.hxx>
#include <editeng/editview.hxx>
#include <editeng/flditem.hxx>
#include <editeng/justifyitem.hxx>
#include <editeng/outliner.hxx>
#include <editeng/misspellrange.hxx>
#include <editeng/editobj.hxx>
#include <o3tl/unit_conversion.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
@@ -48,8 +49,8 @@
#include <sot/formats.hxx>
#include <comphelper/classids.hxx>
#include <svx/drawitem.hxx>
#include <svx/svdview.hxx>
#include <editeng/outliner.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdpagv.hxx>
#include <svtools/optionsdrawinglayer.hxx>
@@ -127,6 +128,9 @@
#include <inputopt.hxx>
#include <queryparam.hxx>
#include <officecfg/Office/Common.hxx>
#include <svx/PaletteManager.hxx>
#include <svx/sdrpagewindow.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <vcl/svapp.hxx>
@@ -495,6 +499,7 @@ struct AutoFilterData : public ScCheckListMenuControl::ExtendedData
class AutoFilterAction : public ScCheckListMenuControl::Action
{
protected:
VclPtr<ScGridWindow> mpWindow;
ScGridWindow::AutoFilterMode meMode;
public:
@@ -523,6 +528,242 @@ public:
}
};
class AutoFilterSubMenuAction : public AutoFilterAction
{
protected:
ScListSubMenuControl* m_pSubMenu;
public:
AutoFilterSubMenuAction(ScGridWindow* p, ScListSubMenuControl* pSubMenu, ScGridWindow::AutoFilterMode eMode)
: AutoFilterAction(p, eMode)
, m_pSubMenu(pSubMenu)
{
}
};
class AutoFilterColorAction : public AutoFilterSubMenuAction
{
private:
Color m_aColor;
public:
AutoFilterColorAction(ScGridWindow* p, ScListSubMenuControl* pSubMenu, ScGridWindow::AutoFilterMode eMode, const Color& rColor)
: AutoFilterSubMenuAction(p, pSubMenu, eMode)
, m_aColor(rColor)
{
}
virtual bool execute() override
{
const AutoFilterData* pData =
static_cast<const AutoFilterData*>(m_pSubMenu->getExtendedData());
if (!pData)
return false;
ScDBData* pDBData = pData->mpData;
if (!pDBData)
return false;
const ScAddress& rPos = pData->maPos;
ScViewData& rViewData = m_pSubMenu->GetViewData();
ScDocument& rDoc = rViewData.GetDocument();
ScQueryParam aParam;
pDBData->GetQueryParam(aParam);
// Try to use the existing entry for the column (if one exists).
ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true);
if (!pEntry)
{
// Something went terribly wrong!
return false;
}
if (ScTabViewShell::isAnyEditViewInRange(rViewData.GetViewShell(), /*bColumns*/ false, aParam.nRow1, aParam.nRow2))
return false;
pEntry->bDoQuery = true;
pEntry->nField = rPos.Col();
pEntry->eConnect = SC_AND;
ScFilterEntries aFilterEntries;
rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries);
bool bActive = false;
auto aItem = pEntry->GetQueryItem();
if (aItem.maColor == m_aColor
&& ((meMode == ScGridWindow::AutoFilterMode::TextColor
&& aItem.meType == ScQueryEntry::ByTextColor)
|| (meMode == ScGridWindow::AutoFilterMode::BackgroundColor
&& aItem.meType == ScQueryEntry::ByBackgroundColor)))
{
bActive = true;
}
// Disable color filter when active color was selected
if (bActive)
{
aParam.RemoveAllEntriesByField(rPos.Col());
pEntry = nullptr; // invalidated by RemoveAllEntriesByField call
// tdf#46184 reset filter options to default values
aParam.eSearchType = utl::SearchParam::SearchType::Normal;
aParam.bCaseSens = false;
aParam.bDuplicate = true;
aParam.bInplace = true;
}
else
{
if (meMode == ScGridWindow::AutoFilterMode::TextColor)
pEntry->SetQueryByTextColor(m_aColor);
else
pEntry->SetQueryByBackgroundColor(m_aColor);
}
rViewData.GetView()->Query(aParam, nullptr, true);
pDBData->SetQueryParam(aParam);
return true;
}
};
class AutoFilterColorPopupStartAction : public AutoFilterSubMenuAction
{
public:
AutoFilterColorPopupStartAction(ScGridWindow* p, ScListSubMenuControl* pSubMenu, ScGridWindow::AutoFilterMode eMode)
: AutoFilterSubMenuAction(p, pSubMenu, eMode)
{
}
virtual bool execute() override
{
const AutoFilterData* pData =
static_cast<const AutoFilterData*>(m_pSubMenu->getExtendedData());
if (!pData)
return false;
ScDBData* pDBData = pData->mpData;
if (!pDBData)
return false;
ScViewData& rViewData = m_pSubMenu->GetViewData();
ScDocument& rDoc = rViewData.GetDocument();
const ScAddress& rPos = pData->maPos;
ScFilterEntries aFilterEntries;
rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries);
m_pSubMenu->clearMenuItems();
std::set<Color> aColors = meMode == ScGridWindow::AutoFilterMode::TextColor
? aFilterEntries.getTextColors()
: aFilterEntries.getBackgroundColors();
XColorListRef xUserColorList;
OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
PaletteManager aPaletteManager;
std::vector<OUString> aPaletteNames = aPaletteManager.GetPaletteList();
for (size_t i = 0, nLen = aPaletteNames.size(); i < nLen; ++i)
{
if (aPaletteName == aPaletteNames[i])
{
aPaletteManager.SetPalette(i);
xUserColorList = XPropertyList::AsColorList(
XPropertyList::CreatePropertyListFromURL(
XPropertyListType::Color, aPaletteManager.GetSelectedPalettePath()));
if (!xUserColorList->Load())
xUserColorList = nullptr;
break;
}
}
ScQueryParam aParam;
pDBData->GetQueryParam(aParam);
ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true);
for (auto& rColor : aColors)
{
bool bActive = false;
if (pEntry)
{
auto aItem = pEntry->GetQueryItem();
if (aItem.maColor == rColor
&& ((meMode == ScGridWindow::AutoFilterMode::TextColor
&& aItem.meType == ScQueryEntry::ByTextColor)
|| (meMode == ScGridWindow::AutoFilterMode::BackgroundColor
&& aItem.meType == ScQueryEntry::ByBackgroundColor)))
{
bActive = true;
}
}
const bool bAutoColor = rColor == COL_AUTO;
// ColorListBox::ShowPreview is similar
ScopedVclPtr<VirtualDevice> xDev(m_pSubMenu->create_virtual_device());
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());
xDev->SetOutputSize(aImageSize);
const tools::Rectangle aRect(Point(0, 0), aImageSize);
if (bAutoColor)
{
const Color aW(COL_WHITE);
const Color aG(0xef, 0xef, 0xef);
int nMinDim = std::min(aImageSize.Width(), aImageSize.Height()) + 1;
int nCheckSize = nMinDim / 3;
xDev->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), std::min(nCheckSize, 8), aW, aG);
xDev->SetFillColor();
}
else
xDev->SetFillColor(rColor);
xDev->SetLineColor(rStyleSettings.GetDisableColor());
xDev->DrawRect(aRect);
if (bAutoColor)
{
OUString sText = meMode == ScGridWindow::AutoFilterMode::TextColor
? ScResId(SCSTR_FILTER_AUTOMATIC_COLOR)
: ScResId(SCSTR_FILTER_NO_FILL);
m_pSubMenu->addMenuCheckItem(sText, bActive, *xDev,
new AutoFilterColorAction(mpWindow, m_pSubMenu, meMode, rColor));
}
else
{
OUString sName;
bool bFoundColorName = false;
if (xUserColorList)
{
sal_Int32 nPos = xUserColorList->GetIndexOfColor(rColor);
if (nPos != -1)
{
XColorEntry* pColorEntry = xUserColorList->GetColor(nPos);
sName = pColorEntry->GetName();
bFoundColorName = true;
}
}
if (!bFoundColorName)
sName = "#" + rColor.AsRGBHexString().toAsciiUpperCase();
m_pSubMenu->addMenuCheckItem(sName, bActive, *xDev,
new AutoFilterColorAction(mpWindow, m_pSubMenu, meMode, rColor));
}
}
m_pSubMenu->resizeToFitMenuItems();
return false;
}
};
class AddItemToEntry
{
ScQueryEntry::QueryItemsType& mrItems;
@@ -594,7 +835,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
weld::Window* pPopupParent = GetFrameWeld();
int nColWidth = ScViewData::ToPixel(rDoc.GetColWidth(nCol, nTab), mrViewData.GetPPTX());
mpAutoFilterPopup.reset(new ScCheckListMenuControl(pPopupParent, &rDoc,
mpAutoFilterPopup.reset(new ScCheckListMenuControl(pPopupParent, mrViewData,
aFilterEntries.mbHasDates, nColWidth, pNotifier));
int nMaxTextWidth = 0;
@@ -735,10 +976,10 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
mpAutoFilterPopup->addMenuItem(
ScResId(SCSTR_FILTER_NOTEMPTY), new AutoFilterAction(this, AutoFilterMode::NonEmpty));
mpAutoFilterPopup->addSeparator();
mpAutoFilterPopup->addMenuItem(
ScResId(SCSTR_FILTER_TEXT_COLOR), new AutoFilterAction(this, AutoFilterMode::TextColor), true);
mpAutoFilterPopup->addMenuItem(
ScResId(SCSTR_FILTER_BACKGROUND_COLOR), new AutoFilterAction(this, AutoFilterMode::BackgroundColor), true);
if (ScListSubMenuControl* pSubMenu = mpAutoFilterPopup->addSubMenuItem(ScResId(SCSTR_FILTER_TEXT_COLOR), true, true))
pSubMenu->setPopupStartAction(new AutoFilterColorPopupStartAction(this, pSubMenu, AutoFilterMode::TextColor));
if (ScListSubMenuControl* pSubMenu = mpAutoFilterPopup->addSubMenuItem(ScResId(SCSTR_FILTER_BACKGROUND_COLOR), true, true))
pSubMenu->setPopupStartAction(new AutoFilterColorPopupStartAction(this, pSubMenu, AutoFilterMode::BackgroundColor));
mpAutoFilterPopup->addSeparator();
mpAutoFilterPopup->addMenuItem(
ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom));
@@ -922,91 +1163,8 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
break;
case AutoFilterMode::TextColor:
case AutoFilterMode::BackgroundColor:
{
ScFilterEntries aFilterEntries;
rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries);
weld::Window* pWindow = GetFrameWeld();
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pWindow, "modules/scalc/ui/colormenu.ui"));
std::unique_ptr<weld::Menu> xColorMenu(xBuilder->weld_menu("menu"));
std::set<Color> aColors = eMode == AutoFilterMode::TextColor
? aFilterEntries.getTextColors()
: aFilterEntries.getBackgroundColors();
sal_Int32 i = 1;
sal_Int32 nActive = -1;
for (auto& rColor : aColors)
{
if (rColor == COL_AUTO)
{
OUString sText = eMode == AutoFilterMode::TextColor
? ScResId(SCSTR_FILTER_AUTOMATIC_COLOR)
: ScResId(SCSTR_FILTER_NO_FILL);
xColorMenu->append_check(OUString::number(i), sText);
}
else
{
// ColorListBox::ShowPreview is similar
ScopedVclPtr<VirtualDevice> xDev(pWindow->create_virtual_device());
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());
xDev->SetOutputSize(aImageSize);
const tools::Rectangle aRect(Point(0, 0), aImageSize);
xDev->SetFillColor(rColor);
xDev->SetLineColor(rStyleSettings.GetDisableColor());
xDev->DrawRect(aRect);
xColorMenu->insert(-1, OUString::number(i), OUString(),
nullptr, xDev.get(), nullptr, TRISTATE_TRUE);
}
auto aItem = pEntry->GetQueryItem();
if (aItem.maColor == rColor
&& ((eMode == AutoFilterMode::TextColor
&& aItem.meType == ScQueryEntry::ByTextColor)
|| (eMode == AutoFilterMode::BackgroundColor
&& aItem.meType == ScQueryEntry::ByBackgroundColor)))
{
nActive = i;
xColorMenu->set_active(OString::number(i), true);
}
i++;
}
sal_Int32 nSelected = mpAutoFilterPopup->ExecuteMenu(*xColorMenu);
xColorMenu.reset();
if (nSelected == 0)
return;
mpAutoFilterPopup->terminateAllPopupMenus();
// Disable color filter when active color was selected
if (nSelected == nActive)
{
aParam.RemoveAllEntriesByField(rPos.Col());
pEntry = nullptr; // invalidated by RemoveAllEntriesByField call
// tdf#46184 reset filter options to default values
aParam.eSearchType = utl::SearchParam::SearchType::Normal;
aParam.bCaseSens = false;
aParam.bDuplicate = true;
aParam.bInplace = true;
}
else
{
// Get selected color from set
std::set<Color>::iterator it = aColors.begin();
std::advance(it, nSelected - 1);
Color selectedColor = *it;
if (eMode == AutoFilterMode::TextColor)
pEntry->SetQueryByTextColor(selectedColor);
else
pEntry->SetQueryByBackgroundColor(selectedColor);
}
}
assert(false && "should be handled by AutoFilterColorAction::execute");
break;
break;
default:
// We don't know how to handle this!
diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx
index bf9e41b..a7cd96a 100644
--- a/sc/source/ui/view/gridwin2.cxx
+++ b/sc/source/ui/view/gridwin2.cxx
@@ -474,7 +474,7 @@ void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScr
pNotifier = SfxViewShell::Current();
weld::Window* pPopupParent = GetFrameWeld();
mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, &mrViewData.GetDocument(),
mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, mrViewData,
false, -1, pNotifier));
mpDPFieldPopup->setExtendedData(std::move(pDPData));
@@ -519,7 +519,7 @@ void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScr
ScResId(STR_MENU_SORT_DESC),
new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::DESCENDING, 0, pViewShell));
ScListSubMenuControl* pSubMenu = mpDPFieldPopup->addSubMenuItem(ScResId(STR_MENU_SORT_CUSTOM), !aUserSortNames.empty());
ScListSubMenuControl* pSubMenu = mpDPFieldPopup->addSubMenuItem(ScResId(STR_MENU_SORT_CUSTOM), !aUserSortNames.empty(), false);
if (pSubMenu)
{
size_t n = aUserSortNames.size();
diff --git a/sc/uiconfig/scalc/ui/filtersubdropdown.ui b/sc/uiconfig/scalc/ui/filtersubdropdown.ui
index 5785bd9..eb9d344 100644
--- a/sc/uiconfig/scalc/ui/filtersubdropdown.ui
+++ b/sc/uiconfig/scalc/ui/filtersubdropdown.ui
@@ -2,14 +2,20 @@
<!-- Generated with glade 3.38.2 -->
<interface domain="sc">
<requires lib="gtk+" version="3.20"/>
<object class="GtkTreeStore" id="liststore1">
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name text -->
<!-- column-name check1 -->
<column type="gboolean"/>
<!-- column-name surface -->
<column type="CairoSurface"/>
<!-- column-name text1 -->
<column type="gchararray"/>
<!-- column-name image1 -->
<column type="GdkPixbuf"/>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name checkvis1 -->
<column type="gboolean"/>
<!-- column-name checktri1 -->
<column type="gboolean"/>
</columns>
</object>
<object class="GtkPopover" id="FilterSubDropDown">
@@ -52,9 +58,10 @@
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<object class="GtkCellRendererToggle" id="cellrenderertoggle"/>
<attributes>
<attribute name="text">0</attribute>
<attribute name="visible">4</attribute>
<attribute name="active">0</attribute>
</attributes>
</child>
</object>
@@ -62,9 +69,19 @@
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
<child>
<object class="GtkCellRendererPixbuf" id="cellrenderertext55"/>
<object class="GtkCellRendererPixbuf" id="cellrendererpixbuf"/>
<attributes>
<attribute name="pixbuf">1</attribute>
<attribute name="surface">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn3">
<child>
<object class="GtkCellRendererText" id="cellrenderertext"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>