diff --git a/offapi/com/sun/star/sheet/ConditionEntryType.idl b/offapi/com/sun/star/sheet/ConditionEntryType.idl index 0266e6721474..5b717850c87b 100644 --- a/offapi/com/sun/star/sheet/ConditionEntryType.idl +++ b/offapi/com/sun/star/sheet/ConditionEntryType.idl @@ -20,6 +20,14 @@ constants ConditionEntryType const long ICONSET = 3; const long DATE = 4; + + /** A color scale conditional format with a min and a max + */ + const long COLORSCALE2 = 5; + + /** A color scale conditional format with a min, a middle and a max + */ + const long COLORSCALE3 = 6; }; diff --git a/sc/CppunitTest_sc_color_scale_api.mk b/sc/CppunitTest_sc_color_scale_api.mk new file mode 100644 index 000000000000..fcfbbe0e67b0 --- /dev/null +++ b/sc/CppunitTest_sc_color_scale_api.mk @@ -0,0 +1,77 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_color_scale_api, \ + sc/qa/extras/color_scale_api \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_color_scale_api, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_color_scale_api, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + drawinglayercore \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sb \ + sc \ + scqahelper \ + sfx \ + sot \ + subsequenttest \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tk \ + tl \ + ucbhelper \ + unotest \ + utl \ + $(call gb_Helper_optional,SCRIPTING, \ + vbahelper) \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_color_scale_api,\ + -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/qa/unit \ + -I$(SRCDIR)/sc/source/ui/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_ure,sc_color_scale_api)) +$(eval $(call gb_CppunitTest_use_vcl,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_color_scale_api,services)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_color_scale_api)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk index 2a58bca9e8ea..75cc2075686e 100644 --- a/sc/Module_sc.mk +++ b/sc/Module_sc.mk @@ -81,6 +81,7 @@ endif $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_anchor_test \ + CppunitTest_sc_color_scale_api \ CppunitTest_sc_cond_format \ CppunitTest_sc_cond_format_merge \ CppunitTest_sc_copypaste \ diff --git a/sc/qa/extras/color_scale_api.cxx b/sc/qa/extras/color_scale_api.cxx new file mode 100644 index 000000000000..cf2a08ae1063 --- /dev/null +++ b/sc/qa/extras/color_scale_api.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +namespace sc_apitest +{ +class ScColorScaleTest : public ScModelTestBase +{ +public: + ScColorScaleTest(); + + void setUp() override; + void tearDown() override; + + void testCreateColorScale2(); + void testCreateColorScale3(); + + CPPUNIT_TEST_SUITE(ScColorScaleTest); + CPPUNIT_TEST(testCreateColorScale2); + CPPUNIT_TEST(testCreateColorScale3); + CPPUNIT_TEST_SUITE_END(); + +private: + uno::Reference m_xMSF; + uno::Reference m_xDoc; + uno::Reference m_xSheets; + uno::Reference m_xSheet; + uno::Reference m_xSheetProperties; + uno::Reference m_xConditionalFormats; +}; + +ScColorScaleTest::ScColorScaleTest() + : ScModelTestBase(u"sc/qa/extras/testdocuments/"_ustr) +{ +} + +void ScColorScaleTest::setUp() +{ + ScModelTestBase::setUp(); + + createScDoc(); + + m_xMSF.set(mxComponent, uno::UNO_QUERY_THROW); + m_xDoc.set(mxComponent, uno::UNO_QUERY_THROW); + m_xSheets.set(m_xDoc->getSheets(), uno::UNO_QUERY_THROW); + m_xSheet.set(m_xSheets->getByIndex(0), uno::UNO_QUERY_THROW); + m_xSheetProperties.set(m_xSheet, uno::UNO_QUERY_THROW); + m_xConditionalFormats.set(m_xSheetProperties->getPropertyValue("ConditionalFormats"), + uno::UNO_QUERY_THROW); +} + +void ScColorScaleTest::tearDown() +{ + m_xConditionalFormats.clear(); + m_xSheetProperties.clear(); + m_xSheet.clear(); + m_xSheets.clear(); + m_xDoc.clear(); + m_xMSF.clear(); + + ScModelTestBase::tearDown(); +} + +void ScColorScaleTest::testCreateColorScale2() +{ + // Tests creating a COLORSCALE2. This should allocate two entries that we can modify. See + // tdf#171950. This also tests tdf#172333 as a side effect. + + // Set color scale conditional formatting on A1:A2 + uno::Reference xRanges( + m_xMSF->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY_THROW); + table::CellRangeAddress a1a2 = { 0, 0, 0, 0, 1 }; + xRanges->addRangeAddress(a1a2, false); + m_xConditionalFormats->createByRange(xRanges); + uno::Reference xConditionalFormat + = m_xConditionalFormats->getConditionalFormats()[0]; + xConditionalFormat->createEntry(sheet::ConditionEntryType::COLORSCALE2, 0); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xConditionalFormat->getCount()); + + uno::Reference xEntry(xConditionalFormat->getByIndex(0), + uno::UNO_QUERY_THROW); + uno::Sequence> aColorScales; + CPPUNIT_ASSERT(xEntry->getPropertyValue("ColorScaleEntries") >>= aColorScales); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aColorScales.getLength()); + + aColorScales[0]->setColor(sal_Int32(COL_MAGENTA)); + aColorScales[0]->setType(sheet::ColorScaleEntryType::COLORSCALE_MIN); + + aColorScales[1]->setColor(sal_Int32(COL_BROWN)); + aColorScales[1]->setType(sheet::ColorScaleEntryType::COLORSCALE_MAX); + + // Put 50 in A1 to make a minimum value + insertStringToCell(u"A1"_ustr, u"50"); + // Put 100 in A2 to make a maximum value + insertStringToCell(u"A2"_ustr, u"100"); + + // A1 should be magenta + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 0, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 0, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 0, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_MAGENTA, aColor); + } + // A2 should be brown + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 1, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 1, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 1, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_BROWN, aColor); + } +} + +void ScColorScaleTest::testCreateColorScale3() +{ + // Tests creating a COLORSCALE3. This should allocate three entries that we can modify. See + // tdf#171950. This also tests tdf#172333 as a side effect. + + // Set color scale conditional formatting on A1:A3 + uno::Reference xRanges( + m_xMSF->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY_THROW); + table::CellRangeAddress a1a3 = { 0, 0, 0, 0, 2 }; + xRanges->addRangeAddress(a1a3, false); + m_xConditionalFormats->createByRange(xRanges); + uno::Reference xConditionalFormat + = m_xConditionalFormats->getConditionalFormats()[0]; + xConditionalFormat->createEntry(sheet::ConditionEntryType::COLORSCALE3, 0); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xConditionalFormat->getCount()); + + uno::Reference xEntry(xConditionalFormat->getByIndex(0), + uno::UNO_QUERY_THROW); + uno::Sequence> aColorScales; + CPPUNIT_ASSERT(xEntry->getPropertyValue("ColorScaleEntries") >>= aColorScales); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aColorScales.getLength()); + + aColorScales[0]->setColor(sal_Int32(COL_MAGENTA)); + aColorScales[0]->setType(sheet::ColorScaleEntryType::COLORSCALE_MIN); + + aColorScales[1]->setColor(sal_Int32(COL_BROWN)); + aColorScales[1]->setType(sheet::ColorScaleEntryType::COLORSCALE_VALUE); + aColorScales[1]->setFormula("75"); + + aColorScales[2]->setColor(sal_Int32(COL_RED)); + aColorScales[2]->setType(sheet::ColorScaleEntryType::COLORSCALE_MAX); + + // Put 50 in A1 to make a minimum value + insertStringToCell(u"A1"_ustr, u"50"); + // Put 75 in A2 to make a middle value + insertStringToCell(u"A2"_ustr, u"75"); + // Put 100 in A3 to make a maximum value + insertStringToCell(u"A3"_ustr, u"100"); + + // A1 should be magenta + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 0, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 0, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 0, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_MAGENTA, aColor); + } + // A2 should be brown + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 1, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 1, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 1, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_BROWN, aColor); + } + // A3 should be red + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 2, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 2, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 2, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_RED, aColor); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ScColorScaleTest); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/ui/unoobj/condformatuno.cxx b/sc/source/ui/unoobj/condformatuno.cxx index d897797a675a..d481db9b588f 100644 --- a/sc/source/ui/unoobj/condformatuno.cxx +++ b/sc/source/ui/unoobj/condformatuno.cxx @@ -469,6 +469,21 @@ ScDocShell* ScCondFormatObj::getDocShell() return mpDocShell; } +namespace +{ +ScColorScaleFormat* createColorScaleFormat(ScDocument& rDoc, size_t nEntries) +{ + ScColorScaleFormat* pNewEntry = new ScColorScaleFormat(rDoc); + + for (size_t i = 0; i < nEntries; ++i) + pNewEntry->AddEntry(new ScColorScaleEntry); + + pNewEntry->EnsureSize(); + + return pNewEntry; +} +} + void ScCondFormatObj::createEntry(const sal_Int32 nType, const sal_Int32 nPos) { SolarMutexGuard aGuard; @@ -485,8 +500,13 @@ void ScCondFormatObj::createEntry(const sal_Int32 nType, const sal_Int32 nPos) rDoc, pFormat->GetRange().GetTopLeftCorner(), u""_ustr); break; case sheet::ConditionEntryType::COLORSCALE: - pNewEntry = new ScColorScaleFormat(rDoc); - static_cast(pNewEntry)->EnsureSize(); + pNewEntry = createColorScaleFormat(rDoc, 0); + break; + case sheet::ConditionEntryType::COLORSCALE2: + pNewEntry = createColorScaleFormat(rDoc, 2); + break; + case sheet::ConditionEntryType::COLORSCALE3: + pNewEntry = createColorScaleFormat(rDoc, 3); break; case sheet::ConditionEntryType::DATABAR: pNewEntry = new ScDataBarFormat(rDoc); @@ -855,7 +875,15 @@ ScColorScaleFormat* ScColorScaleFormatObj::getCoreObject() sal_Int32 ScColorScaleFormatObj::getType() { - return sheet::ConditionEntryType::COLORSCALE; + switch (getCoreObject()->size()) + { + case 2: + return sheet::ConditionEntryType::COLORSCALE2; + case 3: + return sheet::ConditionEntryType::COLORSCALE3; + default: + return sheet::ConditionEntryType::COLORSCALE; + } } uno::Reference SAL_CALL ScColorScaleFormatObj::getPropertySetInfo()