diff --git a/desktop/qa/data/ThemeDocument.docx b/desktop/qa/data/ThemeDocument.docx new file mode 100644 index 000000000000..4dbba883d9b6 Binary files /dev/null and b/desktop/qa/data/ThemeDocument.docx differ diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 74db478c09a3..b698cc5976b7 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -219,6 +219,7 @@ public: void testRenderSearchResult_CommonNode(); void testNoDuplicateTableSelection(); void testMultiViewTableSelection(); + void testColorPaletteCallback(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -291,6 +292,7 @@ public: CPPUNIT_TEST(testRenderSearchResult_CommonNode); CPPUNIT_TEST(testNoDuplicateTableSelection); CPPUNIT_TEST(testMultiViewTableSelection); + CPPUNIT_TEST(testColorPaletteCallback); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -2160,12 +2162,14 @@ class ViewCallback public: OString m_aCellFormula; int m_nTableSelectionCount; + int m_nColorPaletteCallbackCount = 0; bool m_bEmptyTableSelection; bool m_bTilesInvalidated; bool m_bZeroCursor; tools::Rectangle m_aOwnCursor; boost::property_tree::ptree m_aCommentCallbackResult; boost::property_tree::ptree m_aCallbackWindowResult; + boost::property_tree::ptree m_aColorPaletteCallbackResult; bool m_bWindowHidden; ViewCallback(LibLODocument_Impl* pDocument) @@ -2245,6 +2249,14 @@ public: ++m_nTableSelectionCount; } break; + case LOK_CALLBACK_COLOR_PALETTES: + { + m_aColorPaletteCallbackResult.clear(); + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, m_aColorPaletteCallbackResult); + ++m_nColorPaletteCallbackCount; + } + break; } } }; @@ -3525,6 +3537,34 @@ void DesktopLOKTest::testMultiViewTableSelection() CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection); } +void DesktopLOKTest::testColorPaletteCallback() +{ + LibLODocument_Impl* pDocument = loadDoc("ThemeDocument.docx"); + + // Create view 1. + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView1(pDocument); + Scheduler::ProcessEventsToIdle(); + { + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nColorPaletteCallbackCount); + boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); + CPPUNIT_ASSERT(!aValues.empty()); + CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); + } + + // Create view 2. + pDocument->m_pDocumentClass->createView(pDocument); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView2(pDocument); + Scheduler::ProcessEventsToIdle(); + { + CPPUNIT_ASSERT_EQUAL(1, aView2.m_nColorPaletteCallbackCount); + boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); + CPPUNIT_ASSERT(!aValues.empty()); + CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); + } +} + namespace { constexpr size_t classOffset(int i) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 13922571d9ce..52cd5411a7e5 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1816,6 +1816,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) case LOK_CALLBACK_A11Y_FOCUS_CHANGED: case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: + case LOK_CALLBACK_COLOR_PALETTES: { const auto& pos = std::find(m_queue1.rbegin(), m_queue1.rend(), type); auto pos2 = toQueue2(pos); @@ -1877,6 +1878,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) case LOK_CALLBACK_A11Y_FOCUS_CHANGED: case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: + case LOK_CALLBACK_COLOR_PALETTES: { if (removeAll(type)) SAL_INFO("lok", "Removed dups of [" << type << "]: [" << aCallbackData.getPayload() << "]."); diff --git a/docmodel/source/color/ComplexColorJSON.cxx b/docmodel/source/color/ComplexColorJSON.cxx index d04e2c1e339b..db36f29e6a4e 100644 --- a/docmodel/source/color/ComplexColorJSON.cxx +++ b/docmodel/source/color/ComplexColorJSON.cxx @@ -12,7 +12,6 @@ #include #include #include -#include namespace model::color { @@ -57,10 +56,9 @@ bool convertFromJSON(OString const& rJsonString, model::ComplexColor& rComplexCo return true; } -OString convertToJSON(model::ComplexColor const& rComplexColor) +void convertToJSONTree(boost::property_tree::ptree& rTree, model::ComplexColor const& rComplexColor) { - boost::property_tree::ptree aTree; - aTree.put("ThemeIndex", sal_Int16(rComplexColor.getSchemeType())); + rTree.put("ThemeIndex", sal_Int16(rComplexColor.getSchemeType())); boost::property_tree::ptree aTransformationsList; for (auto const& rTransformation : rComplexColor.getTransformations()) @@ -91,10 +89,15 @@ OString convertToJSON(model::ComplexColor const& rComplexColor) aTransformationsList.push_back(std::make_pair("", aChild)); } } - aTree.add_child("Transformations", aTransformationsList); + rTree.add_child("Transformations", aTransformationsList); +} + +OString convertToJSON(model::ComplexColor const& rComplexColor) +{ + boost::property_tree::ptree aTree; + convertToJSONTree(aTree, rComplexColor); std::stringstream aStream; boost::property_tree::write_json(aStream, aTree); - return OString(aStream.str()); } diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h index 47b2d790738f..d6e46e96aee1 100644 --- a/include/LibreOfficeKit/LibreOfficeKitEnums.h +++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h @@ -955,7 +955,12 @@ typedef enum * } * where [N1,N2] is the range of the text selection inside the focused paragraph. */ - LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED = 64 + LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED = 64, + + /** + * Informs the LibreOfficeKit client that the color palettes have changed. + */ + LOK_CALLBACK_COLOR_PALETTES = 65 } LibreOfficeKitCallbackType; @@ -1114,6 +1119,8 @@ static inline const char* lokCallbackTypeToString(int nType) return "LOK_CALLBACK_A11Y_CARET_CHANGED"; case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: return "LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED"; + case LOK_CALLBACK_COLOR_PALETTES: + return "LOK_CALLBACK_COLOR_PALETTES"; } assert(!"Unknown LibreOfficeKitCallbackType type."); diff --git a/include/docmodel/color/ComplexColorJSON.hxx b/include/docmodel/color/ComplexColorJSON.hxx index bf23e4f0565a..b4aa4bfb3354 100644 --- a/include/docmodel/color/ComplexColorJSON.hxx +++ b/include/docmodel/color/ComplexColorJSON.hxx @@ -12,10 +12,13 @@ #include #include +#include namespace model::color { DOCMODEL_DLLPUBLIC OString convertToJSON(model::ComplexColor const& rComplexColor); +DOCMODEL_DLLPUBLIC void convertToJSONTree(boost::property_tree::ptree& rTree, + model::ComplexColor const& rComplexColor); DOCMODEL_DLLPUBLIC bool convertFromJSON(OString const& rJsonString, model::ComplexColor& rComplexColor); diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx index 778e8c2ee327..6a65712719f1 100644 --- a/include/svx/svdpage.hxx +++ b/include/svx/svdpage.hxx @@ -327,6 +327,7 @@ private: SdrPageProperties& operator=(const SdrPageProperties& rCandidate) = delete; + void sendLOKitThemeChangedCallback(); public: // construct/destruct SdrPageProperties(SdrPage& rSdrPage); diff --git a/include/svx/theme/ThemeColorPaletteManager.hxx b/include/svx/theme/ThemeColorPaletteManager.hxx index 14fbda39248b..d575c1038750 100644 --- a/include/svx/theme/ThemeColorPaletteManager.hxx +++ b/include/svx/theme/ThemeColorPaletteManager.hxx @@ -60,6 +60,7 @@ class SVXCORE_DLLPUBLIC ThemeColorPaletteManager final public: ThemeColorPaletteManager(std::shared_ptr const& pColorSet); ThemePaletteCollection generate(); + OString generateJSON(); }; } // end svx namespace diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 6d810f2d1e3f..305ac5a477d2 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -1491,6 +1491,7 @@ callback (gpointer pData) case LOK_CALLBACK_A11Y_FOCUS_CHANGED: case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: + case LOK_CALLBACK_COLOR_PALETTES: { // TODO: Implement me break; diff --git a/sd/source/ui/inc/ViewShellBase.hxx b/sd/source/ui/inc/ViewShellBase.hxx index ed80658d096c..7ef425416612 100644 --- a/sd/source/ui/inc/ViewShellBase.hxx +++ b/sd/source/ui/inc/ViewShellBase.hxx @@ -217,6 +217,8 @@ public: int getEditMode() const override; /// See SfxViewShell::setEditMode(). void setEditMode(int nMode); + /// See SfxViewShell::afterCallbackRegistered(). + void afterCallbackRegistered() override; /// See SfxViewShell::NotifyCursor(). void NotifyCursor(SfxViewShell* pViewShell) const override; diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx index 64d0950c366c..9099988969d8 100644 --- a/sd/source/ui/view/ViewShellBase.cxx +++ b/sd/source/ui/view/ViewShellBase.cxx @@ -1009,6 +1009,11 @@ void ViewShellBase::setEditMode(int nMode) } } +void ViewShellBase::afterCallbackRegistered() +{ + // TODO: Add theme color palette changed callback +} + void ViewShellBase::NotifyCursor(SfxViewShell* pOtherShell) const { ViewShell* pThisShell = framework::FrameworkHelper::Instance(*const_cast(this))->GetViewShell(FrameworkHelper::msCenterPaneURL).get(); diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx index f7df7c12a730..d165300292f7 100644 --- a/svx/source/svdraw/svdpage.cxx +++ b/svx/source/svdraw/svdpage.cxx @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include @@ -56,6 +58,8 @@ #include #include #include +#include +#include #include @@ -1201,6 +1205,7 @@ SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage) { std::shared_ptr pDefaultColorSet(new model::ColorSet(*pColorSet)); mpTheme->setColorSet(pDefaultColorSet); + sendLOKitThemeChangedCallback(); } } } @@ -1273,8 +1278,13 @@ void SdrPageProperties::SetStyleSheet(SfxStyleSheet* pStyleSheet) void SdrPageProperties::SetTheme(std::shared_ptr const& pTheme) { + if (mpTheme == pTheme) + return; + mpTheme = pTheme; + sendLOKitThemeChangedCallback(); + if (mpTheme && mpTheme->getColorSet() && mpSdrPage->IsMasterPage()) { SdrModel& rModel = mpSdrPage->getSdrModelFromSdrPage(); @@ -1293,6 +1303,15 @@ void SdrPageProperties::SetTheme(std::shared_ptr const& pTheme) } } +void SdrPageProperties::sendLOKitThemeChangedCallback() +{ + if (!comphelper::LibreOfficeKit::isActive()) + return; + + svx::ThemeColorPaletteManager aManager(mpTheme->getColorSet()); + SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); +} + std::shared_ptr const& SdrPageProperties::GetTheme() const { return mpTheme; diff --git a/svx/source/theme/ThemeColorPaletteManager.cxx b/svx/source/theme/ThemeColorPaletteManager.cxx index 82ebb38fb69a..c1fcc9fc0aa7 100644 --- a/svx/source/theme/ThemeColorPaletteManager.cxx +++ b/svx/source/theme/ThemeColorPaletteManager.cxx @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -125,6 +127,47 @@ svx::ThemePaletteCollection ThemeColorPaletteManager::generate() return aThemePaletteCollection; } +OString ThemeColorPaletteManager::generateJSON() +{ + svx::ThemePaletteCollection aThemePaletteCollection = generate(); + + boost::property_tree::ptree aTree; + boost::property_tree::ptree aColorListTree; + + for (size_t nEffect = 0; nEffect < 6; ++nEffect) + { + boost::property_tree::ptree aColorRowTree; + for (size_t nIndex = 0; nIndex < 12; ++nIndex) + { + auto const& rColorData = aThemePaletteCollection.maColors[nIndex]; + auto const& rEffectData = rColorData.maEffects[nEffect]; + + boost::property_tree::ptree aColorTree; + aColorTree.put("Value", rEffectData.maColor.AsRGBHexString().toUtf8()); + aColorTree.put("Name", rEffectData.maColorName.toUtf8()); + + model::ComplexColor aComplexColor; + aComplexColor.setSchemeColor(rColorData.meThemeColorType); + aComplexColor.addTransformation( + { model::TransformationType::LumMod, rEffectData.mnLumMod }); + aComplexColor.addTransformation( + { model::TransformationType::LumMod, rEffectData.mnLumOff }); + boost::property_tree::ptree aDataTree; + model::color::convertToJSONTree(aDataTree, aComplexColor); + aColorTree.add_child("Data", aDataTree); + aColorRowTree.push_back(std::make_pair("", aColorTree)); + } + aColorListTree.push_back(std::make_pair("", aColorRowTree)); + } + + aTree.add_child("ThemeColors", aColorListTree); + + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTree); + + return OString(aStream.str()); +} + } // end svx namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx index 60fe6fdc7303..89b5ad6f391b 100644 --- a/sw/inc/view.hxx +++ b/sw/inc/view.hxx @@ -670,6 +670,8 @@ public: void dumpAsXml(xmlTextWriterPtr pWriter) const override; void SetRedlineAuthor(const OUString& rAuthor); const OUString& GetRedlineAuthor() const; + /// See SfxViewShell::afterCallbackRegistered(). + void afterCallbackRegistered() override; /// See SfxViewShell::NotifyCursor(). void NotifyCursor(SfxViewShell* pViewShell) const override; void ShowUIElement(const OUString& sElementURL) const; diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index b035e53eb38f..dcd88c9e05d4 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +101,7 @@ #include #include #include - +#include #include #include @@ -1177,6 +1178,18 @@ SwView::~SwView() m_pFormatClipboard.reset(); } +void SwView::afterCallbackRegistered() +{ + if (!comphelper::LibreOfficeKit::isActive()) + return; + auto* pDocShell = GetDocShell(); + if (pDocShell) + { + svx::ThemeColorPaletteManager aManager(pDocShell->GetThemeColors()); + libreOfficeKitViewCallback(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); + } +} + SwDocShell* SwView::GetDocShell() { SfxObjectShell* pDocShell = GetViewFrame().GetObjectShell();