summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2021-04-21 09:53:54 +0200
committerSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2021-05-03 09:32:17 +0200
commit5a4bd9bfbdb881368c202bc766f893a5c672621e (patch)
treed3f37369f5085e1f343ebb38c2ed13cd9ed8cc72
parent95d8eb87eb20351a2e5795fc8c16653c0f58d6b4 (diff)
tdf#76258 Filter by colors
UI/Logic implementation Change-Id: If7b48219caa466d8a3341bdc4e104d696e8988c5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114385 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
-rw-r--r--include/vcl/menu.hxx4
-rw-r--r--sc/inc/filterentries.hxx10
-rw-r--r--sc/inc/queryentry.hxx14
-rw-r--r--sc/inc/strings.hrc2
-rw-r--r--sc/source/core/data/column3.cxx28
-rw-r--r--sc/source/core/data/table3.cxx36
-rw-r--r--sc/source/core/tool/queryentry.cxx24
-rw-r--r--sc/source/ui/cctrl/checklistmenu.cxx4
-rw-r--r--sc/source/ui/inc/gridwin.hxx13
-rw-r--r--sc/source/ui/view/gridwin.cxx41
-rw-r--r--vcl/source/window/menu.cxx12
11 files changed, 178 insertions, 10 deletions
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index f48a4e427d06..7bc136d680f7 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -24,6 +24,7 @@
#include <string_view>
#include <vcl/vclenum.hxx>
+#include <tools/color.hxx>
#include <tools/link.hxx>
#include <tools/long.hxx>
#include <vcl/dllapi.h>
@@ -309,6 +310,9 @@ public:
void SetItemImage( sal_uInt16 nItemId, const Image& rImage );
Image GetItemImage( sal_uInt16 nItemId ) const;
+ // Instead of an image, draw a color
+ void SetItemColor( sal_uInt16 nItemId, const Color& rColor );
+
void SetItemCommand( sal_uInt16 nItemId, const OUString& rCommand );
OUString GetItemCommand( sal_uInt16 nItemId ) const;
diff --git a/sc/inc/filterentries.hxx b/sc/inc/filterentries.hxx
index 2a8dccd99cb3..6cbe4c43a929 100644
--- a/sc/inc/filterentries.hxx
+++ b/sc/inc/filterentries.hxx
@@ -13,12 +13,15 @@
#include <sal/config.h>
#include "typedstrdata.hxx"
#include <vector>
+#include <tools/color.hxx>
struct ScFilterEntries
{
std::vector<ScTypedStrData> maStrData;
bool mbHasDates;
bool mbHasEmpties;
+ std::set<Color> maTextColors;
+ std::set<Color> maBackgroundColors;
ScFilterEntries() : mbHasDates(false), mbHasEmpties(false) {}
@@ -32,6 +35,13 @@ struct ScFilterEntries
bool empty() const { return maStrData.empty(); }
void push_back( const ScTypedStrData& r ) { maStrData.push_back(r); }
void push_back( ScTypedStrData&& r ) { maStrData.push_back(r); }
+ std::set<Color>& getTextColors() { return maTextColors; };
+ void addTextColor(const Color& aTextColor) { maTextColors.emplace(aTextColor); }
+ std::set<Color>& getBackgroundColors() { return maBackgroundColors; };
+ void addBackgroundColor(const Color& aBackgroundColor)
+ {
+ maBackgroundColors.emplace(aBackgroundColor);
+ }
};
#endif
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 9b94f7cdcf6b..f7a7f6896934 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -22,6 +22,7 @@
#include "global.hxx"
#include <svl/sharedstring.hxx>
#include <unotools/textsearch.hxx>
+#include <tools/color.hxx>
#include <memory>
#include <vector>
@@ -31,7 +32,15 @@
*/
struct SC_DLLPUBLIC ScQueryEntry
{
- enum QueryType { ByValue, ByString, ByDate, ByEmpty };
+ enum QueryType
+ {
+ ByValue,
+ ByString,
+ ByDate,
+ ByEmpty,
+ ByTextColor,
+ ByBackgroundColor,
+ };
struct SAL_DLLPRIVATE Item
{
@@ -40,6 +49,7 @@ struct SC_DLLPUBLIC ScQueryEntry
svl::SharedString maString;
bool mbMatchEmpty;
bool mbFormattedValue;
+ Color maColor;
Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false), mbFormattedValue(false) {}
@@ -68,6 +78,8 @@ struct SC_DLLPUBLIC ScQueryEntry
bool IsQueryByEmpty() const;
void SetQueryByNonEmpty();
bool IsQueryByNonEmpty() const;
+ void SetQueryByTextColor(Color color);
+ void SetQueryByBackgroundColor(Color color);
const Item& GetQueryItem() const { return GetQueryItemImpl(); }
Item& GetQueryItem() { return GetQueryItemImpl(); }
void Clear();
diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc
index b52355f03527..d2463ad39306 100644
--- a/sc/inc/strings.hrc
+++ b/sc/inc/strings.hrc
@@ -34,6 +34,8 @@
#define SCSTR_TOP10FILTER NC_("SCSTR_TOP10FILTER", "Top 10")
#define SCSTR_FILTER_EMPTY NC_("SCSTR_FILTER_EMPTY", "Empty")
#define SCSTR_FILTER_NOTEMPTY NC_("SCSTR_FILTER_NOTEMPTY", "Not Empty")
+#define SCSTR_FILTER_TEXT_COLOR NC_("SCSTR_FILTER_TEXT_COLOR", "Text color")
+#define SCSTR_FILTER_BACKGROUND_COLOR NC_("SCSTR_FILTER_BACKGROUND_COLOR", "Background color")
#define SCSTR_NONAME NC_("SCSTR_NONAME", "unnamed")
// "%1 is replaced to column letter, such as 'Column A'"
#define SCSTR_COLUMN NC_("SCSTR_COLUMN", "Column %1")
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 7a90c00db4e6..712595aab369 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -44,6 +44,8 @@
#include <sharedformula.hxx>
#include <listenercontext.hxx>
#include <filterentries.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
#include <com/sun/star/i18n/LocaleDataItem2.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
@@ -2416,16 +2418,26 @@ class FilterEntriesHandler
ScColumn& mrColumn;
ScFilterEntries& mrFilterEntries;
- void processCell(SCROW nRow, ScRefCellValue& rCell)
+ void processCell(ScColumn& rColumn, SCROW nRow, ScRefCellValue& rCell)
{
SvNumberFormatter* pFormatter = mrColumn.GetDoc().GetFormatTable();
OUString aStr;
sal_uLong nFormat = mrColumn.GetNumberFormat(mrColumn.GetDoc().GetNonThreadedContext(), nRow);
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrColumn.GetDoc(), mrColumn.HasFiltering());
+ // Colors
+ ScAddress aPos(rColumn.GetCol(), nRow, rColumn.GetTab());
+ const SvxColorItem* pColor = rColumn.GetDoc().GetAttr(aPos, ATTR_FONT_COLOR);
+ Color textColor = pColor->GetValue();
+
+ const SvxBrushItem* pBrush = rColumn.GetDoc().GetAttr(aPos, ATTR_BACKGROUND);
+ Color backgroundColor = pBrush->GetColor();
+
if (rCell.hasString())
{
mrFilterEntries.push_back(ScTypedStrData(aStr));
+ mrFilterEntries.addTextColor(textColor);
+ mrFilterEntries.addBackgroundColor(backgroundColor);
return;
}
@@ -2448,6 +2460,8 @@ class FilterEntriesHandler
if (!aErr.isEmpty())
{
mrFilterEntries.push_back(ScTypedStrData(aErr));
+ mrFilterEntries.addTextColor(textColor);
+ mrFilterEntries.addBackgroundColor(backgroundColor);
return;
}
}
@@ -2483,6 +2497,8 @@ class FilterEntriesHandler
}
// maybe extend ScTypedStrData enum is also an option here
mrFilterEntries.push_back(ScTypedStrData(aStr, fVal, ScTypedStrData::Value,bDate));
+ mrFilterEntries.addTextColor(textColor);
+ mrFilterEntries.addBackgroundColor(backgroundColor);
}
public:
@@ -2492,25 +2508,25 @@ public:
void operator() (size_t nRow, double fVal)
{
ScRefCellValue aCell(fVal);
- processCell(nRow, aCell);
+ processCell(mrColumn, nRow, aCell);
}
void operator() (size_t nRow, const svl::SharedString& rStr)
{
ScRefCellValue aCell(&rStr);
- processCell(nRow, aCell);
+ processCell(mrColumn, nRow, aCell);
}
void operator() (size_t nRow, const EditTextObject* p)
{
ScRefCellValue aCell(p);
- processCell(nRow, aCell);
+ processCell(mrColumn, nRow, aCell);
}
void operator() (size_t nRow, const ScFormulaCell* p)
{
ScRefCellValue aCell(const_cast<ScFormulaCell*>(p));
- processCell(nRow, aCell);
+ processCell(mrColumn, nRow, aCell);
}
void operator() (const int nElemType, size_t nRow, size_t /* nDataSize */)
@@ -2525,7 +2541,7 @@ public:
return;
}
ScRefCellValue aCell = mrColumn.GetCellValue(nRow);
- processCell(nRow, aCell);
+ processCell(mrColumn, nRow, aCell);
}
};
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 93cd3f9dd5b2..dcc76104280b 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -19,6 +19,8 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/random.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
#include <unotools/textsearch.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
@@ -2695,6 +2697,26 @@ public:
return std::pair<bool,bool>(bOk, bTestEqual);
}
+ std::pair<bool, bool> compareByTextColor(SCCOL nCol, SCROW nRow, SCTAB nTab,
+ const ScQueryEntry::Item& rItem)
+ {
+ ScAddress aPos(nCol, nRow, nTab);
+ const SvxColorItem* pColor = mrDoc.GetAttr(aPos, ATTR_FONT_COLOR);
+ Color color = pColor->GetValue();
+ bool bMatch = rItem.maColor == color;
+ return std::pair<bool, bool>(bMatch, false);
+ }
+
+ std::pair<bool, bool> compareByBackgroundColor(SCCOL nCol, SCROW nRow, SCTAB nTab,
+ const ScQueryEntry::Item& rItem)
+ {
+ ScAddress aPos(nCol, nRow, nTab);
+ const SvxBrushItem* pBrush = mrDoc.GetAttr(aPos, ATTR_BACKGROUND);
+ Color color = pBrush->GetColor();
+ bool bMatch = rItem.maColor == color;
+ return std::pair<bool, bool>(bMatch, false);
+ }
+
// To be called only if both isQueryByValue() and isQueryByString()
// returned false and range lookup is wanted! In range lookup comparison
// numbers are less than strings. Nothing else is compared.
@@ -2809,6 +2831,20 @@ bool ScTable::ValidQuery(
aRes.first |= aThisRes.first;
aRes.second |= aThisRes.second;
}
+ if (rItem.meType == ScQueryEntry::ByTextColor)
+ {
+ std::pair<bool, bool> aThisRes
+ = aEval.compareByTextColor(nCol, nRow, nTab, rItem);
+ aRes.first |= aThisRes.first;
+ aRes.second |= aThisRes.second;
+ }
+ if (rItem.meType == ScQueryEntry::ByBackgroundColor)
+ {
+ std::pair<bool,bool> aThisRes =
+ aEval.compareByBackgroundColor(nCol, nRow, nTab, rItem);
+ aRes.first |= aThisRes.first;
+ aRes.second |= aThisRes.second;
+ }
else if (rParam.mbRangeLookup)
{
std::pair<bool,bool> aThisRes =
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index a295759e0c3c..836b2caf7dd8 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -29,6 +29,8 @@
#define SC_EMPTYFIELDS (double(0x0042))
#define SC_NONEMPTYFIELDS (double(0x0043))
+#define SC_TEXTCOLOR (double(0x0044))
+#define SC_BACKGROUNDCOLOR (double(0x0045))
bool ScQueryEntry::Item::operator== (const Item& r) const
{
@@ -115,6 +117,28 @@ bool ScQueryEntry::IsQueryByNonEmpty() const
rItem.mfVal == SC_NONEMPTYFIELDS;
}
+void ScQueryEntry::SetQueryByTextColor(Color color)
+{
+ eOp = SC_EQUAL;
+ maQueryItems.resize(1);
+ Item& rItem = maQueryItems[0];
+ rItem.meType = ByTextColor;
+ rItem.maString = svl::SharedString();
+ rItem.mfVal = SC_TEXTCOLOR;
+ rItem.maColor = color;
+}
+
+void ScQueryEntry::SetQueryByBackgroundColor(Color color)
+{
+ eOp = SC_EQUAL;
+ maQueryItems.resize(1);
+ Item& rItem = maQueryItems[0];
+ rItem.meType = ByBackgroundColor;
+ rItem.maString = svl::SharedString();
+ rItem.mfVal = SC_BACKGROUNDCOLOR;
+ rItem.maColor = color;
+}
+
ScQueryEntry::Item& ScQueryEntry::GetQueryItemImpl() const
{
if (maQueryItems.size() != 1)
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 4200457956fe..f825335f5af6 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -197,9 +197,9 @@ void ScCheckListMenuControl::executeMenuItem(size_t nPos)
// no action is defined.
return;
- terminateAllPopupMenus();
-
maMenuItems[nPos].mxAction->execute();
+
+ terminateAllPopupMenus();
}
void ScCheckListMenuControl::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer)
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 950d574a1ec7..023715a33c8a 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -322,7 +322,18 @@ protected:
virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
public:
- enum class AutoFilterMode { Normal, Top10, Custom, Empty, NonEmpty, SortAscending, SortDescending };
+ enum class AutoFilterMode
+ {
+ Normal,
+ Top10,
+ Custom,
+ Empty,
+ NonEmpty,
+ TextColor,
+ BackgroundColor,
+ SortAscending,
+ SortDescending,
+ };
ScGridWindow( vcl::Window* pParent, ScViewData& rData, ScSplitPos eWhichPos );
virtual ~ScGridWindow() override;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 59c0868e7c31..3a60311691b5 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -705,6 +705,11 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
ScResId(SCSTR_FILTER_NOTEMPTY), new AutoFilterAction(this, AutoFilterMode::NonEmpty));
rControl.addSeparator();
rControl.addMenuItem(
+ ScResId(SCSTR_FILTER_TEXT_COLOR), new AutoFilterAction(this, AutoFilterMode::TextColor));
+ rControl.addMenuItem(
+ ScResId(SCSTR_FILTER_BACKGROUND_COLOR), new AutoFilterAction(this, AutoFilterMode::BackgroundColor));
+ rControl.addSeparator();
+ rControl.addMenuItem(
ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom));
rControl.initMembers(nMaxTextWidth + 20); // 20 pixel estimated for the checkbox
@@ -869,6 +874,42 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
case AutoFilterMode::NonEmpty:
pEntry->SetQueryByNonEmpty();
break;
+ case AutoFilterMode::TextColor:
+ case AutoFilterMode::BackgroundColor:
+ {
+ ScFilterEntries aFilterEntries;
+ rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries);
+
+ VclPtr<PopupMenu> pColorMenu = VclPtr<PopupMenu>::Create();
+ std::set<Color> aColors = eMode == AutoFilterMode::TextColor
+ ? aFilterEntries.getTextColors()
+ : aFilterEntries.getBackgroundColors();
+ sal_Int32 i = 1;
+ for (auto& rColor : aColors)
+ {
+ pColorMenu->InsertItem(i, OUString(), MenuItemBits::CHECKABLE);
+ pColorMenu->SetItemColor(i, rColor);
+ i++;
+ }
+
+ sal_uInt16 nSelected = pColorMenu->Execute(this, mpAutoFilterPopup->GetPosPixel());
+ pColorMenu.disposeAndClear();
+
+ if (nSelected == 0)
+ break;
+
+ // 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);
+ }
+
+ break;
default:
// We don't know how to handle this!
return;
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 233f531cfcaf..a1d39df63bf0 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -21,6 +21,7 @@
#include <sal/log.hxx>
#include <comphelper/lok.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
#include <vcl/svapp.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/image.hxx>
@@ -1022,6 +1023,17 @@ OUString Menu::GetItemText( sal_uInt16 nItemId ) const
return OUString();
}
+void Menu::SetItemColor(sal_uInt16 nItemId, const Color& rColor)
+{
+ Bitmap aBmp(Size(50, 50), vcl::PixelFormat::N24_BPP);
+ BitmapWriteAccess aBmpAccess(aBmp);
+ aBmpAccess.SetFillColor(rColor);
+ aBmpAccess.FillRect(tools::Rectangle(0, 0, 49, 49));
+ BitmapEx aBmpEx(aBmp);
+ Image aImage(aBmpEx);
+ SetItemImage(nItemId, aImage);
+}
+
void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
{
size_t nPos;