include/sfx2/classificationhelper.hxx | 6 sfx2/source/view/classificationhelper.cxx | 37 +++- sw/source/core/edit/edfcol.cxx | 246 +++++++++++++++++++++++++++--- 3 files changed, 263 insertions(+), 26 deletions(-)
New commits: commit 9cf13c9f07311731757127ba50bd3f2eb0d22272 Author: Miklos Vajna <[email protected]> Date: Wed Feb 24 17:11:51 2016 +0100 sw classification: don't insert multiple watermark objects in header If the text is different, remove the old shape and then insert the new one. Otherwise just don't insert a new (identical) shape. Delete and insert is needed because the shape size depends on its textural content. Change-Id: I0c8faa0e3e69416ea0b89fa33155826bc2dc7a4f diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 14ef654..9acb496 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -20,6 +20,7 @@ #include <editsh.hxx> #include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> #include <com/sun/star/document/XActionLockable.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/HomogenMatrix3.hpp> @@ -112,6 +113,47 @@ bool lcl_hasField(const uno::Reference<text::XText>& xText, const OUString& rSer return false; } +/// Search for a frame named rShapeName of type rServiceName in xText. +uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, const OUString& rShapeName) +{ + uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); + while (xParagraphs->hasMoreElements()) + { + uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration(); + while (xTextPortions->hasMoreElements()) + { + uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY); + OUString aTextPortionType; + xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType; + if (aTextPortionType != "Frame") + continue; + + uno::Reference<container::XContentEnumerationAccess> xContentEnumerationAccess(xTextPortion, uno::UNO_QUERY); + if (!xContentEnumerationAccess.is()) + continue; + + uno::Reference<container::XEnumeration> xEnumeration = xContentEnumerationAccess->createContentEnumeration("com.sun.star.text.TextContent"); + if (!xEnumeration->hasMoreElements()) + continue; + + uno::Reference<lang::XServiceInfo> xWatermark(xEnumeration->nextElement(), uno::UNO_QUERY); + if (!xWatermark->supportsService(rServiceName)) + continue; + + uno::Reference<container::XNamed> xNamed(xWatermark, uno::UNO_QUERY); + if (xNamed->getName() != rShapeName) + continue; + + uno::Reference<drawing::XShape> xShape(xWatermark, uno::UNO_QUERY); + return xShape; + } + } + + return uno::Reference<drawing::XShape>(); +} + } // anonymous namespace SwTextFormatColl& SwEditShell::GetDfltTextFormatColl() const @@ -184,103 +226,122 @@ void SwEditShell::SetClassification(const OUString& rName) if (!aWatermark.isEmpty()) { - // Calc the ratio. - double fRatio = 0; - OutputDevice* pOut = Application::GetDefaultDevice(); - vcl::Font aFont(pOut->GetFont()); - fRatio = aFont.GetFontSize().Height(); - fRatio /= pOut->GetTextWidth(aWatermark); - - // Calc the size. - sal_Int32 nWidth = 0; - awt::Size aSize; - xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize; - if (aSize.Width < aSize.Height) + OUString aShapeServiceName = "com.sun.star.drawing.CustomShape"; + uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, SfxClassificationHelper::PROP_DOCWATERMARK()); + + if (xWatermark.is()) { - // Portrait. - sal_Int32 nLeftMargin = 0; - xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin; - sal_Int32 nRightMargin = 0; - xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin; - nWidth = aSize.Width - nLeftMargin - nRightMargin; + // If the header already contains a watermark, see if it its text is up to date. + uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY); + if (xTextRange->getString() != aWatermark) + { + // No: delete it and we'll insert a replacement. + uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY); + xComponent->dispose(); + xWatermark.clear(); + } } - else + + if (!xWatermark.is()) { - // Landscape. - sal_Int32 nTopMargin = 0; - xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin; - sal_Int32 nBottomMargin = 0; - xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin; - nWidth = aSize.Height - nTopMargin - nBottomMargin; + // Calc the ratio. + double fRatio = 0; + OutputDevice* pOut = Application::GetDefaultDevice(); + vcl::Font aFont(pOut->GetFont()); + fRatio = aFont.GetFontSize().Height(); + fRatio /= pOut->GetTextWidth(aWatermark); + + // Calc the size. + sal_Int32 nWidth = 0; + awt::Size aSize; + xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize; + if (aSize.Width < aSize.Height) + { + // Portrait. + sal_Int32 nLeftMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin; + sal_Int32 nRightMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin; + nWidth = aSize.Width - nLeftMargin - nRightMargin; + } + else + { + // Landscape. + sal_Int32 nTopMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin; + sal_Int32 nBottomMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin; + nWidth = aSize.Height - nTopMargin - nBottomMargin; + } + sal_Int32 nHeight = nWidth * fRatio; + + // Create and insert the shape. + uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance(aShapeServiceName), uno::UNO_QUERY); + basegfx::B2DHomMatrix aTransformation; + aTransformation.identity(); + aTransformation.scale(nWidth, nHeight); + aTransformation.rotate(F_PI180 * -45); + drawing::HomogenMatrix3 aMatrix; + aMatrix.Line1.Column1 = aTransformation.get(0, 0); + aMatrix.Line1.Column2 = aTransformation.get(0, 1); + aMatrix.Line1.Column3 = aTransformation.get(0, 2); + aMatrix.Line2.Column1 = aTransformation.get(1, 0); + aMatrix.Line2.Column2 = aTransformation.get(1, 1); + aMatrix.Line2.Column3 = aTransformation.get(1, 2); + aMatrix.Line3.Column1 = aTransformation.get(2, 0); + aMatrix.Line3.Column2 = aTransformation.get(2, 1); + aMatrix.Line3.Column3 = aTransformation.get(2, 2); + uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY); + xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false); + + // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering. + uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY); + xLockable->addActionLock(); + xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0))); + xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID)); + xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50))); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); + xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE)); + xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT)); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); + xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans"))); + xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix)); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER))); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER))); + + uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY); + xTextRange->setString(aWatermark); + + uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); + xDefaulter->createCustomShapeDefaults("fontwork-plain-text"); + + auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >(); + auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"TextPath", uno::makeAny(true)}, + })); + auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue) + { + return rValue.Name == "TextPath"; + }); + if (it == aGeomPropVec.end()) + aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues)); + else + it->Value <<= aPropertyValues; + xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); + + uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY); + xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK()); + xLockable->removeActionLock(); } - sal_Int32 nHeight = nWidth * fRatio; - - // Create and insert the shape. - uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY); - basegfx::B2DHomMatrix aTransformation; - aTransformation.identity(); - aTransformation.scale(nWidth, nHeight); - aTransformation.rotate(F_PI180 * -45); - drawing::HomogenMatrix3 aMatrix; - aMatrix.Line1.Column1 = aTransformation.get(0, 0); - aMatrix.Line1.Column2 = aTransformation.get(0, 1); - aMatrix.Line1.Column3 = aTransformation.get(0, 2); - aMatrix.Line2.Column1 = aTransformation.get(1, 0); - aMatrix.Line2.Column2 = aTransformation.get(1, 1); - aMatrix.Line2.Column3 = aTransformation.get(1, 2); - aMatrix.Line3.Column1 = aTransformation.get(2, 0); - aMatrix.Line3.Column2 = aTransformation.get(2, 1); - aMatrix.Line3.Column3 = aTransformation.get(2, 2); - uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); - uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY); - xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false); - - // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering. - uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY); - xLockable->addActionLock(); - xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0))); - xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID)); - xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50))); - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); - xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE)); - xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false)); - xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false)); - xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false)); - xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight)); - xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth)); - xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT)); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); - xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans"))); - xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix)); - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER))); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER))); - - uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY); - xTextRange->setString(aWatermark); - - uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); - xDefaulter->createCustomShapeDefaults("fontwork-plain-text"); - - auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >(); - auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq); - uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( - { - {"TextPath", uno::makeAny(true)}, - })); - auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue) - { - return rValue.Name == "TextPath"; - }); - if (it == aGeomPropVec.end()) - aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues)); - else - it->Value <<= aPropertyValues; - xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); - - uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY); - xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK()); - xLockable->removeActionLock(); } } commit bff9f2d469736d20261ba8ff488dd98452e3fe88 Author: Miklos Vajna <[email protected]> Date: Wed Feb 24 16:45:01 2016 +0100 sw classification: name watermark objects, so later it's possible to find them Given that they are not fields, it's necessary to re-create them every time their textural content would change. Change-Id: I1276ef686b1b622dccaa8ac4996af8e4cb4de329 diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx index 1f37cb7..c84f7ce 100644 --- a/include/sfx2/classificationhelper.hxx +++ b/include/sfx2/classificationhelper.hxx @@ -51,6 +51,8 @@ public: static const OUString& PROP_DOCHEADER(); /// Brief text located at the bottom of each document's pages. static const OUString& PROP_DOCFOOTER(); + /// Brief text formatted as a watermark on each document's page. + static const OUString& PROP_DOCWATERMARK(); }; #endif diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx index d2e123d..3ff9047 100644 --- a/sfx2/source/view/classificationhelper.cxx +++ b/sfx2/source/view/classificationhelper.cxx @@ -165,7 +165,7 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception) rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:4"].clear(); rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()].clear(); rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()].clear(); - rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"].clear(); + rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCWATERMARK()].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-first-line-of-text"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-last-line-of-text"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-subject-prefix"].clear(); @@ -239,7 +239,7 @@ void SAL_CALL SfxClassificationParser::endElement(const OUString& rName) throw ( else if (m_aIdentifier == "Document: Footer") m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()] = m_aValue; else if (m_aIdentifier == "Document: Watermark") - m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"] = m_aValue; + m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCWATERMARK()] = m_aValue; } } } @@ -486,7 +486,7 @@ basegfx::BColor SfxClassificationHelper::GetImpactLevelColor() OUString SfxClassificationHelper::GetDocumentWatermark() { - std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find("urn:bails:IntellectualProperty:Marking:document-watermark"); + std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCWATERMARK()); if (it != m_pImpl->m_aLabels.end()) return it->second; @@ -542,4 +542,10 @@ const OUString& SfxClassificationHelper::PROP_DOCFOOTER() return sProp; } +const OUString& SfxClassificationHelper::PROP_DOCWATERMARK() +{ + static OUString sProp("urn:bails:IntellectualProperty:Marking:document-watermark"); + return sProp; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 62403d8..14ef654 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -277,6 +277,9 @@ void SwEditShell::SetClassification(const OUString& rName) else it->Value <<= aPropertyValues; xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); + + uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY); + xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK()); xLockable->removeActionLock(); } } commit cc3d29dc412902ea8d6a85426ba72b77166a8c95 Author: Miklos Vajna <[email protected]> Date: Wed Feb 24 16:15:54 2016 +0100 sw classification: put watermark shape to the header if policy wants so Change-Id: Ib22b2066bb3f4059425b8c71b5fc737e160aef0b diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 43a1390..62403d8 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -19,13 +19,29 @@ #include <editsh.hxx> -#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/document/XActionLockable.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/HomogenMatrix3.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> - -#include <hintids.hxx> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/text/RelOrientation.hpp> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> #include <editeng/formatbreakitem.hxx> +#include <editeng/unoprnms.hxx> #include <sfx2/classificationhelper.hxx> +#include <vcl/svapp.hxx> + +#include <hintids.hxx> #include <doc.hxx> #include <IDocumentUndoRedo.hxx> #include <edimp.hxx> @@ -125,35 +141,40 @@ void SwEditShell::SetClassification(const OUString& rName) bool bHeaderIsNeeded = aHelper.HasDocumentHeader(); bool bFooterIsNeeded = aHelper.HasDocumentFooter(); + OUString aWatermark = aHelper.GetDocumentWatermark(); - if (bHeaderIsNeeded || bFooterIsNeeded) + if (!bHeaderIsNeeded && !bFooterIsNeeded && aWatermark.isEmpty()) + return; + + uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + + std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); + for (const OUString& rPageStyleName : aUsedPageStyles) { - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); - uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); - uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); - uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); + OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); - std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); - for (const OUString& rPageStyleName : aUsedPageStyles) + if (bHeaderIsNeeded || !aWatermark.isEmpty()) { - uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); - OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; + // If the header is off, turn it on. + bool bHeaderIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; + if (!bHeaderIsOn) + xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true)); + + // If the header already contains a document header field, no need to do anything. + uno::Reference<text::XText> xHeaderText; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; if (bHeaderIsNeeded) { - // If the header is off, turn it on. - bool bHeaderIsOn = false; - xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; - if (!bHeaderIsOn) - xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true)); - - // If the header already contains a document header field, no need to do anything. - uno::Reference<text::XText> xHeaderText; - xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER())) { // Append a field to the end of the header text. - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER())); uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); @@ -161,26 +182,123 @@ void SwEditShell::SetClassification(const OUString& rName) } } - if (bFooterIsNeeded) + if (!aWatermark.isEmpty()) { - // If the footer is off, turn it on. - bool bFooterIsOn = false; - xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn; - if (!bFooterIsOn) - xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true)); - - // If the footer already contains a document header field, no need to do anything. - uno::Reference<text::XText> xFooterText; - xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText; - if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER())) + // Calc the ratio. + double fRatio = 0; + OutputDevice* pOut = Application::GetDefaultDevice(); + vcl::Font aFont(pOut->GetFont()); + fRatio = aFont.GetFontSize().Height(); + fRatio /= pOut->GetTextWidth(aWatermark); + + // Calc the size. + sal_Int32 nWidth = 0; + awt::Size aSize; + xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize; + if (aSize.Width < aSize.Height) { - // Append a field to the end of the footer text. - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); - xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER())); - uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); - xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false); + // Portrait. + sal_Int32 nLeftMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin; + sal_Int32 nRightMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin; + nWidth = aSize.Width - nLeftMargin - nRightMargin; + } + else + { + // Landscape. + sal_Int32 nTopMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin; + sal_Int32 nBottomMargin = 0; + xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin; + nWidth = aSize.Height - nTopMargin - nBottomMargin; } + sal_Int32 nHeight = nWidth * fRatio; + + // Create and insert the shape. + uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY); + basegfx::B2DHomMatrix aTransformation; + aTransformation.identity(); + aTransformation.scale(nWidth, nHeight); + aTransformation.rotate(F_PI180 * -45); + drawing::HomogenMatrix3 aMatrix; + aMatrix.Line1.Column1 = aTransformation.get(0, 0); + aMatrix.Line1.Column2 = aTransformation.get(0, 1); + aMatrix.Line1.Column3 = aTransformation.get(0, 2); + aMatrix.Line2.Column1 = aTransformation.get(1, 0); + aMatrix.Line2.Column2 = aTransformation.get(1, 1); + aMatrix.Line2.Column3 = aTransformation.get(1, 2); + aMatrix.Line3.Column1 = aTransformation.get(2, 0); + aMatrix.Line3.Column2 = aTransformation.get(2, 1); + aMatrix.Line3.Column3 = aTransformation.get(2, 2); + uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY); + xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false); + + // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering. + uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY); + xLockable->addActionLock(); + xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0))); + xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID)); + xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50))); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); + xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE)); + xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth)); + xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT)); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA))); + xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans"))); + xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix)); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER))); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER))); + + uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY); + xTextRange->setString(aWatermark); + + uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); + xDefaulter->createCustomShapeDefaults("fontwork-plain-text"); + + auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >(); + auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"TextPath", uno::makeAny(true)}, + })); + auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue) + { + return rValue.Name == "TextPath"; + }); + if (it == aGeomPropVec.end()) + aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues)); + else + it->Value <<= aPropertyValues; + xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); + xLockable->removeActionLock(); + } + } + + if (bFooterIsNeeded) + { + // If the footer is off, turn it on. + bool bFooterIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn; + if (!bFooterIsOn) + xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true)); + + // If the footer already contains a document header field, no need to do anything. + uno::Reference<text::XText> xFooterText; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText; + if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER())) + { + // Append a field to the end of the footer text. + uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); + xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER())); + uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); + xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false); } } } commit fa72b6e97c5c60eae4a97541cde150ee0d8c0443 Author: Miklos Vajna <[email protected]> Date: Wed Feb 24 14:25:19 2016 +0100 sw classification: put the relevant field to the footer if policy wants so Change-Id: I61c235660366ec1aba137097600605aae76c39a7 diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx index 0e279c7..1f37cb7 100644 --- a/include/sfx2/classificationhelper.hxx +++ b/include/sfx2/classificationhelper.hxx @@ -43,10 +43,14 @@ public: OUString GetDocumentWatermark(); /// The selected category has some content for the document header. bool HasDocumentHeader(); + /// The selected category has some content for the document footer. + bool HasDocumentFooter(); void UpdateInfobar(SfxViewFrame& rViewFrame); /// Brief text located at the top of each document's pages. static const OUString& PROP_DOCHEADER(); + /// Brief text located at the bottom of each document's pages. + static const OUString& PROP_DOCFOOTER(); }; #endif diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx index 5680e1a..d2e123d 100644 --- a/sfx2/source/view/classificationhelper.cxx +++ b/sfx2/source/view/classificationhelper.cxx @@ -163,8 +163,8 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception) rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:2"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:3"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:4"].clear(); - rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-footer"].clear(); - rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-header"].clear(); + rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()].clear(); + rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-first-line-of-text"].clear(); rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-last-line-of-text"].clear(); @@ -235,9 +235,9 @@ void SAL_CALL SfxClassificationParser::endElement(const OUString& rName) throw ( if (m_pCategory) { if (m_aIdentifier == "Document: Header") - m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-header"] = m_aValue; + m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()] = m_aValue; else if (m_aIdentifier == "Document: Footer") - m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-footer"] = m_aValue; + m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()] = m_aValue; else if (m_aIdentifier == "Document: Watermark") m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"] = m_aValue; } @@ -418,7 +418,16 @@ bool SfxClassificationHelper::HasImpactLevel() bool SfxClassificationHelper::HasDocumentHeader() { - std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find("urn:bails:IntellectualProperty:Marking:document-header"); + std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCHEADER()); + if (it == m_pImpl->m_aLabels.end() || it->second.isEmpty()) + return false; + + return true; +} + +bool SfxClassificationHelper::HasDocumentFooter() +{ + std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCFOOTER()); if (it == m_pImpl->m_aLabels.end() || it->second.isEmpty()) return false; @@ -527,4 +536,10 @@ const OUString& SfxClassificationHelper::PROP_DOCHEADER() return sProp; } +const OUString& SfxClassificationHelper::PROP_DOCFOOTER() +{ + static OUString sProp("urn:bails:IntellectualProperty:Marking:document-footer"); + return sProp; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index cb8124c..43a1390 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -123,7 +123,10 @@ void SwEditShell::SetClassification(const OUString& rName) // This updates the infobar as well. aHelper.SetBACName(rName); - if (aHelper.HasDocumentHeader()) + bool bHeaderIsNeeded = aHelper.HasDocumentHeader(); + bool bFooterIsNeeded = aHelper.HasDocumentFooter(); + + if (bHeaderIsNeeded || bFooterIsNeeded) { uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); @@ -134,25 +137,50 @@ void SwEditShell::SetClassification(const OUString& rName) for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); + OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; - // If the header is off, turn it on. - bool bHeaderIsOn = false; - xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; - if (!bHeaderIsOn) - xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true)); + if (bHeaderIsNeeded) + { + // If the header is off, turn it on. + bool bHeaderIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; + if (!bHeaderIsOn) + xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true)); + + // If the header already contains a document header field, no need to do anything. + uno::Reference<text::XText> xHeaderText; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; + if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER())) + { + // Append a field to the end of the header text. + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); + xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER())); + uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); + xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, /*bAbsorb=*/false); + } + } - // If the header already contains a document header field, no need to do anything. - uno::Reference<text::XText> xHeaderText; - xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; - OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; - if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER())) + if (bFooterIsNeeded) { - // Append a field to the end of the header text. - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); - xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER())); - uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); - xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, /*bAbsorb=*/false); + // If the footer is off, turn it on. + bool bFooterIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn; + if (!bFooterIsOn) + xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true)); + + // If the footer already contains a document header field, no need to do anything. + uno::Reference<text::XText> xFooterText; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText; + if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER())) + { + // Append a field to the end of the footer text. + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); + xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER())); + uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); + xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false); + } } } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
