diff options
author | Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de> | 2021-04-21 09:53:54 +0200 |
---|---|---|
committer | Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de> | 2021-05-03 09:32:17 +0200 |
commit | 5a4bd9bfbdb881368c202bc766f893a5c672621e (patch) | |
tree | d3f37369f5085e1f343ebb38c2ed13cd9ed8cc72 | |
parent | 95d8eb87eb20351a2e5795fc8c16653c0f58d6b4 (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.hxx | 4 | ||||
-rw-r--r-- | sc/inc/filterentries.hxx | 10 | ||||
-rw-r--r-- | sc/inc/queryentry.hxx | 14 | ||||
-rw-r--r-- | sc/inc/strings.hrc | 2 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 28 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 36 | ||||
-rw-r--r-- | sc/source/core/tool/queryentry.cxx | 24 | ||||
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/inc/gridwin.hxx | 13 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 41 | ||||
-rw-r--r-- | vcl/source/window/menu.cxx | 12 |
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; |