[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - 9 commits - include/oox include/sfx2 officecfg/registry oox/source sfx2/Library_sfx.mk sfx2/sdi sfx2/source sw/inc sw/Library_sw.mk sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_swriter.mk

Szymon Kłos szymon.klos at collabora.com
Thu Jun 1 10:52:39 UTC 2017


 include/oox/vml/vmlformatting.hxx                                   |    1 
 include/sfx2/sfxsids.hrc                                            |   10 
 include/sfx2/watermarkitem.hxx                                      |   47 +
 officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu |    8 
 oox/source/export/vmlexport.cxx                                     |    4 
 oox/source/vml/vmlformatting.cxx                                    |   22 
 oox/source/vml/vmlshapecontext.cxx                                  |   12 
 sfx2/Library_sfx.mk                                                 |    1 
 sfx2/sdi/sfx.sdi                                                    |   20 
 sfx2/sdi/sfxitems.sdi                                               |    1 
 sfx2/source/doc/watermarkitem.cxx                                   |   92 ++
 sw/Library_sw.mk                                                    |    1 
 sw/UIConfig_swriter.mk                                              |    1 
 sw/inc/editsh.hxx                                                   |    4 
 sw/qa/extras/ooxmlexport/data/watermark-font.docx                   |binary
 sw/qa/extras/ooxmlexport/ooxmlexport2.cxx                           |   13 
 sw/qa/extras/ooxmlexport/ooxmlexport7.cxx                           |    4 
 sw/qa/extras/uiwriter/data/watermark.docx                           |binary
 sw/qa/extras/uiwriter/uiwriter.cxx                                  |   22 
 sw/sdi/_basesh.sdi                                                  |    6 
 sw/source/core/edit/edfcol.cxx                                      |  374 ++++++----
 sw/source/uibase/app/docsh2.cxx                                     |   34 
 sw/source/uibase/app/docst.cxx                                      |    8 
 sw/source/uibase/dialog/watermarkdialog.cxx                         |  104 ++
 sw/source/uibase/inc/watermarkdialog.hxx                            |   42 +
 sw/source/uibase/shells/basesh.cxx                                  |    5 
 sw/source/uibase/shells/slotadd.cxx                                 |    1 
 sw/uiconfig/swriter/menubar/menubar.xml                             |    1 
 sw/uiconfig/swriter/ui/watermarkdialog.ui                           |  215 +++++
 29 files changed, 921 insertions(+), 132 deletions(-)

New commits:
commit 8d322275b0a4d482296b891a550e538e33986324
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Thu May 25 18:54:37 2017 +0200

    Watermark: VML font-family import for textpath
    
    Handle style attribute to get font-family:
    <v:textpath style="font-family:"DejaVu Sans Light";font-size:1pt" .../>
    
    Change-Id: I5fe530aecccc57e103b413ef494502f666f1005a
    Reviewed-on: https://gerrit.libreoffice.org/38039
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/include/oox/vml/vmlformatting.hxx b/include/oox/vml/vmlformatting.hxx
index d7c3e92f0b9c..efb0e6606887 100644
--- a/include/oox/vml/vmlformatting.hxx
+++ b/include/oox/vml/vmlformatting.hxx
@@ -241,6 +241,7 @@ struct OOX_DLLPUBLIC ShadowModel
 struct OOX_DLLPUBLIC TextpathModel
 {
     OptValue<OUString> moString;                  ///< Specifies the string of the textpath.
+    OptValue<OUString> moStyle;                   ///< Specifies the style of the textpath.
 
     TextpathModel();
 
diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx
index 36cc43dea07d..f37c15d181d6 100644
--- a/oox/source/vml/vmlformatting.cxx
+++ b/oox/source/vml/vmlformatting.cxx
@@ -882,6 +882,28 @@ void TextpathModel::pushToPropMap(ShapePropertyMap& rPropMap, const uno::Referen
         }
         rPropMap.setAnyProperty(PROP_CustomShapeGeometry, uno::makeAny(aGeomPropSeq));
     }
+    if (moStyle.has())
+    {
+        OUString aStyle = moStyle.get(OUString());
+
+        sal_Int32 nIndex = 0;
+        while( nIndex >= 0 )
+        {
+            OUString aName, aValue;
+            if (ConversionHelper::separatePair(aName, aValue, aStyle.getToken(0, ';', nIndex), ':'))
+            {
+                if (aName == "font-family")
+                {
+                    // remove " (first, and last character)
+                    if (aValue.getLength() > 2)
+                        aValue = aValue.copy(1, aValue.getLength() - 2);
+
+                    uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+                    xPropertySet->setPropertyValue("CharFontName", uno::makeAny(aValue));
+                }
+            }
+        }
+    }
 }
 
 } // namespace vml
diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx
index ed369ae1c7d9..02cf06e51429 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -383,6 +383,7 @@ ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const A
         break;
         case VML_TOKEN( textpath ):
             mrTypeModel.maTextpathModel.moString.assignIfUsed(rAttribs.getString(XML_string));
+            mrTypeModel.maTextpathModel.moStyle.assignIfUsed(rAttribs.getString(XML_style));
         break;
     }
     return nullptr;
diff --git a/sw/qa/extras/ooxmlexport/data/watermark-font.docx b/sw/qa/extras/ooxmlexport/data/watermark-font.docx
new file mode 100644
index 000000000000..82d7ec8a83fc
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/watermark-font.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
index 80b5bba9ad9f..636dd76643e6 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
@@ -727,6 +727,19 @@ DECLARE_OOXMLEXPORT_TEST(testWatermark, "watermark.docx")
     CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_NONE, getProperty<drawing::LineStyle>(xShape, "LineStyle"));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testWatermarkFont, "watermark-font.docx")
+{
+    uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("TestFont"), xShape->getString());
+
+    uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+    OUString aFont;
+
+    // Check font family
+    CPPUNIT_ASSERT(xPropertySet->getPropertyValue("CharFontName") >>= aFont);
+    CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Serif"), aFont);
+}
+
 DECLARE_OOXMLEXPORT_TEST(testFdo43093, "fdo43093.docx")
 {
     // The problem was that the alignment are not exchange when the paragraph are RTL.
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index e8c81d6e575b..b3c0ff237025 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -835,8 +835,7 @@ void SwUiWriterTest::testWatermarkDOCX()
 
     const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>(pItem);
     CPPUNIT_ASSERT_EQUAL(OUString("CustomWatermark"), pWatermark->GetText());
-    //TODO: VML import textpath style
-    //CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Sans Light"), pWatermark->GetFont());
+    CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Sans Light"), pWatermark->GetFont());
     CPPUNIT_ASSERT_EQUAL((sal_Int16)45, pWatermark->GetAngle());
     CPPUNIT_ASSERT_EQUAL((sal_uInt32)0x548dd4, pWatermark->GetColor());
     CPPUNIT_ASSERT_EQUAL((sal_Int16)50, pWatermark->GetTransparency());
commit 5bc597c49207be961454cc333425f6d2a9230347
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Wed May 24 00:15:15 2017 +0200

    Watermark: docx interoperability
    
    Before patch:
    
    Document created in MS Word:
    <v:shapetype id="_x0000_t136" o:spt="136" ...>
    <v:shape type="#_x0000_t136" ...>
    
    Imported to LO and exported:
    <v:shapetype id="shapetype_136" o:spt="136" ...>
    <v:shape type="shapetype_136" ...>
    
    Then again imported to MS Word and exported:
    <v:shapetype id="shapetype_136" o:spid="_x0000_m1026" o:spt="100" ...>
    <v:shape type="#shapetype_136" ...>
    
    In this moment LO after import had shape in the navigator but it wasn't visible.
    
    Patch:
    * vmshapecontext.cxx is changed to read ShapeType from id instead of o:spt
                         when o:spid is present.
    * vmlexport.cxx added o:spid for Word to identify inserted watermark
    * edfxol.cxx changed name of shape to "PowerPlusWaterMarkObject" for Word
    * tests
    
    Change-Id: I25322628838a98c45cbeed64144d04977b2ea9ba
    Reviewed-on: https://gerrit.libreoffice.org/37969
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 28de3dce50c2..8ba7d9fb492f 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -197,8 +197,10 @@ void VMLExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uIn
     }
     else
     {
-        // A watermark object - store the optional shape ID also ('o:spid')
+        // A watermark object - store the optional shape ID
         m_pShapeAttrList->add( XML_id, OUStringToOString(m_pSdrObject->GetName(), RTL_TEXTENCODING_UTF8) );
+        // also ('o:spid')
+        m_pShapeAttrList->addNS( XML_o, XML_spid, ShapeIdString( nShapeId ) );
     }
 }
 
diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx
index dc654223aca6..ed369ae1c7d9 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -275,11 +275,18 @@ ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, ShapeType& r
     mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() );
     mrTypeModel.maLegacyId = rAttribs.getString( XML_id, OUString() );
     OSL_ENSURE( !mrTypeModel.maShapeId.isEmpty(), "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
+    // builtin shape type identifier
+    mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
     // if the o:spid attribute exists, the id attribute contains the user-defined shape name
     if( bHasOspid )
+    {
         mrTypeModel.maShapeName = rAttribs.getXString( XML_id, OUString() );
-    // builtin shape type identifier
-    mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
+        // get ShapeType and ShapeId from name for compatibility
+        mrTypeModel.maShapeId = mrTypeModel.maShapeName;
+        static const OUString sShapeTypePrefix = "shapetype_";
+        if( mrTypeModel.maShapeName.startsWith( sShapeTypePrefix ) )
+            mrTypeModel.moShapeType = mrTypeModel.maShapeName.copy(sShapeTypePrefix.getLength()).toInt32();
+    }
 
     // coordinate system position/size, CSS style
     mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
index b538e9f990da..e7f24005cd92 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
@@ -106,6 +106,10 @@ DECLARE_OOXMLEXPORT_TEST(testTextWatermark, "textWatermark.docx")
        return;
 
     assertXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","id","PowerPlusWaterMarkObject93701316");
+
+    //The second problem was that Word uses also "o:spid"
+    const OUString& sSpid = getXPath(pXmlHeader1, "/w:hdr[1]/w:p[1]/w:r[1]/w:pict[1]/v:shape[1]","spid");
+    CPPUNIT_ASSERT(!sSpid.isEmpty());
 }
 
 DECLARE_OOXMLEXPORT_TEST(testPictureWatermark, "pictureWatermark.docx")
diff --git a/sw/qa/extras/uiwriter/data/watermark.docx b/sw/qa/extras/uiwriter/data/watermark.docx
new file mode 100644
index 000000000000..0b26d4442e98
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/watermark.docx differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 4594b5ba4936..e8c81d6e575b 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -100,6 +100,7 @@
 #include <comphelper/configurationhelper.hxx>
 #include <editeng/unolingu.hxx>
 #include <config_features.h>
+#include <sfx2/watermarkitem.hxx>
 
 static const char* DATA_DIRECTORY = "/sw/qa/extras/uiwriter/data/";
 
@@ -121,6 +122,7 @@ public:
     void testDOCXAutoTextMultiple();
     void testDOTMAutoText();
     void testDOCXAutoTextGallery();
+    void testWatermarkDOCX();
     void testTdf67238();
     void testFdo75110();
     void testFdo75898();
@@ -243,6 +245,7 @@ public:
     CPPUNIT_TEST(testDOCXAutoTextMultiple);
     CPPUNIT_TEST(testDOTMAutoText);
     CPPUNIT_TEST(testDOCXAutoTextGallery);
+    CPPUNIT_TEST(testWatermarkDOCX);
     CPPUNIT_TEST(testTdf67238);
     CPPUNIT_TEST(testFdo75110);
     CPPUNIT_TEST(testFdo75898);
@@ -819,6 +822,26 @@ void SwUiWriterTest::testDOCXAutoTextGallery()
     CPPUNIT_ASSERT_EQUAL(OUString("Multiple"), pGlossary->GetLongName(0));
 }
 
+void SwUiWriterTest::testWatermarkDOCX()
+{
+    SwDoc* const pDoc = createDoc("watermark.docx");
+    SwDocShell* pDocShell = pDoc->GetDocShell();
+    const SfxPoolItem* pItem;
+    SfxItemState eState = pDocShell->GetViewShell()->GetViewFrame()->GetDispatcher()->QueryState(SID_WATERMARK, pItem);
+
+    CPPUNIT_ASSERT(eState >= SfxItemState::DEFAULT);
+    CPPUNIT_ASSERT(pItem);
+    CPPUNIT_ASSERT_EQUAL((unsigned short)SID_WATERMARK, pItem->Which());
+
+    const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>(pItem);
+    CPPUNIT_ASSERT_EQUAL(OUString("CustomWatermark"), pWatermark->GetText());
+    //TODO: VML import textpath style
+    //CPPUNIT_ASSERT_EQUAL(OUString("DejaVu Sans Light"), pWatermark->GetFont());
+    CPPUNIT_ASSERT_EQUAL((sal_Int16)45, pWatermark->GetAngle());
+    CPPUNIT_ASSERT_EQUAL((sal_uInt32)0x548dd4, pWatermark->GetColor());
+    CPPUNIT_ASSERT_EQUAL((sal_Int16)50, pWatermark->GetTransparency());
+}
+
 void SwUiWriterTest::testFdo74981()
 {
     // create a document with an input field
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index dc5f4b9d8853..bd139d75799c 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -60,6 +60,8 @@
 #include <pagefrm.hxx>
 #include <sfx2/watermarkitem.hxx>
 
+#define WATERMARK_NAME "PowerPlusWaterMarkObject"
+
 namespace
 {
 
@@ -114,8 +116,8 @@ 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)
+/// Search for a frame with WATERMARK_NAME in name of type rServiceName in xText. Returns found name in rShapeName.
+uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, OUString& rShapeName)
 {
     uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY);
     uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration();
@@ -144,9 +146,12 @@ uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XTex
                 continue;
 
             uno::Reference<container::XNamed> xNamed(xWatermark, uno::UNO_QUERY);
-            if (xNamed->getName() != rShapeName)
+
+            if (!xNamed->getName().match(WATERMARK_NAME))
                 continue;
 
+            rShapeName = xNamed->getName();
+
             uno::Reference<drawing::XShape> xShape(xWatermark, uno::UNO_QUERY);
             return xShape;
         }
@@ -283,7 +288,7 @@ SfxWatermarkItem SwEditShell::GetWatermark()
         xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
 
         OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
-        static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
+        OUString sWatermark = "";
         uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
 
         if (xWatermark.is())
@@ -349,7 +354,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark)
         xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
 
         OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
-        static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
+        OUString sWatermark = WATERMARK_NAME;
         uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
 
         bool bDeleteWatermark = rWatermark.GetText().isEmpty();
@@ -490,7 +495,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark)
             xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
 
             uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
-            xNamed->setName(SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK());
+            xNamed->setName(sWatermark);
             xLockable->removeActionLock();
         }
     }
commit 8421372dd3c25c7852de388e3c8cc4a8b65dc2de
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Thu May 25 15:12:46 2017 +0200

    Watermark: updated Put and QueryValue
    
    Change-Id: Ica65be783130b1981093204edd03dc793a16343b
    Reviewed-on: https://gerrit.libreoffice.org/38027
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Maxim Monastirsky <momonasmon at gmail.com>

diff --git a/sfx2/source/doc/watermarkitem.cxx b/sfx2/source/doc/watermarkitem.cxx
index ebb794fcd73e..f54745694557 100644
--- a/sfx2/source/doc/watermarkitem.cxx
+++ b/sfx2/source/doc/watermarkitem.cxx
@@ -9,6 +9,7 @@
 
 #include <sfx2/watermarkitem.hxx>
 #include <sfx2/sfxsids.hrc>
+#include <comphelper/propertysequence.hxx>
 
 SfxWatermarkItem::SfxWatermarkItem()
 : SfxPoolItem( SID_WATERMARK )
@@ -52,26 +53,36 @@ SfxPoolItem* SfxWatermarkItem::Clone( SfxItemPool *) const
 
 bool SfxWatermarkItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
 {
-    rVal <<= m_aText;
-    rVal <<= m_aFont;
-    rVal <<= m_nAngle;
-    rVal <<= m_nTransparency;
-    rVal <<= m_nColor;
+    rVal <<= comphelper::InitPropertySequence( {
+        { "Text", css::uno::makeAny( m_aText ) },
+        { "Font", css::uno::makeAny( m_aFont ) },
+        { "Angle", css::uno::makeAny( m_nAngle ) },
+        { "Transparency", css::uno::makeAny( m_nTransparency ) },
+        { "Color", css::uno::makeAny( m_nColor ) },
+    } );
 
     return true;
 }
 
 bool SfxWatermarkItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
 {
-    OUString aText;
+    css::uno::Sequence<css::beans::PropertyValue> aSequence;
 
-    if ( rVal >>= aText )
+    if ( rVal >>= aSequence )
     {
-        m_aText = aText;
-        rVal >>= m_aFont;
-        rVal >>= m_nAngle;
-        rVal >>= m_nTransparency;
-        rVal >>= m_nColor;
+        for(const auto& aEntry : aSequence)
+        {
+            if(aEntry.Name == "Text")
+                aEntry.Value >>= m_aText;
+            if(aEntry.Name == "Font")
+                aEntry.Value >>= m_aFont;
+            if(aEntry.Name == "Angle")
+                aEntry.Value >>= m_nAngle;
+            if(aEntry.Name == "Transparency")
+                aEntry.Value >>= m_nTransparency;
+            if(aEntry.Name == "Color")
+                aEntry.Value >>= m_nColor;
+        }
         return true;
     }
 
commit 10c4276c2c8d7a9b6a5243a0d1d7a00ed5b882a0
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Wed May 24 12:59:26 2017 +0200

    tdf#108040 Don't turn on header to check if Watermark exist
    
    Change-Id: Ieaf42384248deb283f71743f68c059b384abaa1a

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index df0dcfabb059..dc5f4b9d8853 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -277,7 +277,7 @@ SfxWatermarkItem SwEditShell::GetWatermark()
         bool bHeaderIsOn = false;
         xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
         if (!bHeaderIsOn)
-            xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
+            return SfxWatermarkItem();
 
         uno::Reference<text::XText> xHeaderText;
         xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
commit e54eb23ac824d3f08cd21f2518c153d255200f9d
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Tue May 23 13:40:24 2017 +0200

    Watermark: read angle value
    
    Change-Id: Ib6b98c58b1251c27476cbbbd03a2f7ed97e68c45
    Reviewed-on: https://gerrit.libreoffice.org/37947
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 4f1967dc9648..df0dcfabb059 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -294,6 +294,7 @@ SfxWatermarkItem SwEditShell::GetWatermark()
             sal_uInt32 nColor;
             sal_Int16 nTransparency;
             OUString aFont;
+            drawing::HomogenMatrix3 aMatrix;
 
             aItem.SetText(xTextRange->getString());
 
@@ -301,7 +302,14 @@ SfxWatermarkItem SwEditShell::GetWatermark()
                 aItem.SetFont(aFont);
             if (xPropertySet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= nColor)
                 aItem.SetColor(nColor);
-            // TODO: aItem.SetAngle(nAngle);
+            if (xPropertySet->getPropertyValue("Transformation") >>= aMatrix)
+            {
+                double y = aMatrix.Line2.Column1;
+                double x = aMatrix.Line1.Column1;
+                double nRad = atan2(y, x) * -1;
+                double nDeg = nRad * 180.0 / F_PI;
+                aItem.SetAngle(nDeg);
+            }
             if (xPropertySet->getPropertyValue(UNO_NAME_FILL_TRANSPARENCE) >>= nTransparency)
                 aItem.SetTransparency(nTransparency);
 
@@ -347,21 +355,28 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark)
         bool bDeleteWatermark = rWatermark.GetText().isEmpty();
         if (xWatermark.is())
         {
+            drawing::HomogenMatrix3 aMatrix;
             sal_uInt32 nColor = 0xc0c0c0;
             sal_Int16 nTransparency = 50;
+            sal_Int16 nAngle = 45;
             OUString aFont = "";
 
             uno::Reference<beans::XPropertySet> xPropertySet(xWatermark, uno::UNO_QUERY);
             xPropertySet->getPropertyValue(UNO_NAME_CHAR_FONT_NAME) >>= aFont;
             xPropertySet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= nColor;
-            // TODO: Angle
             xPropertySet->getPropertyValue(UNO_NAME_FILL_TRANSPARENCE) >>= nTransparency;
+            xPropertySet->getPropertyValue("Transformation") >>= aMatrix;
+            double y = aMatrix.Line2.Column1;
+            double x = aMatrix.Line1.Column1;
+            double nRad = atan2(y, x) * -1;
+            nAngle = nRad * 180.0 / F_PI;
 
             // 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() != rWatermark.GetText()
                 || aFont != rWatermark.GetFont()
                 || nColor != rWatermark.GetColor()
+                || nAngle != rWatermark.GetAngle()
                 || nTransparency != rWatermark.GetTransparency()
                 || bDeleteWatermark)
             {
commit c14fcaa5e8d4d3693e18ea8c60ddf8dde5674da3
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Tue May 23 11:35:30 2017 +0200

    Watermark: move to the insert menu
    
    Change-Id: I6058236434de00cddec1340613e83c10acc4df2a

diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml
index b91238f96df0..a9474f441cb7 100644
--- a/sw/uiconfig/swriter/menubar/menubar.xml
+++ b/sw/uiconfig/swriter/menubar/menubar.xml
@@ -268,6 +268,7 @@
         </menu:menupopup>
       </menu:menu>
       <menu:menuitem menu:id=".uno:FontworkGalleryFloater"/>
+      <menu:menuitem menu:id=".uno:Watermark"/>
       <menu:menuseparator/>
       <menu:menuitem menu:id=".uno:DrawText"/>
       <menu:menuitem menu:id=".uno:InsertAnnotation"/>
diff --git a/sw/uiconfig/swriter/toolbar/classificationbar.xml b/sw/uiconfig/swriter/toolbar/classificationbar.xml
index 01981333a46e..3ee34071e040 100644
--- a/sw/uiconfig/swriter/toolbar/classificationbar.xml
+++ b/sw/uiconfig/swriter/toolbar/classificationbar.xml
@@ -9,5 +9,4 @@
 -->
 <toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink" toolbar:id="toolbar">
   <toolbar:toolbaritem xlink:href=".uno:ClassificationApply"/>
-  <toolbar:toolbaritem xlink:href=".uno:Watermark"/>
 </toolbar:toolbar>
commit eb4f3c80ed695a7f0452b3c5c313750c51c962a5
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Tue May 23 11:29:43 2017 +0200

    Watermark: remove enable checkbox
    
    Change-Id: Ic18b85070bf6c5c3e9678859a87cb9f44411533b

diff --git a/sw/source/uibase/dialog/watermarkdialog.cxx b/sw/source/uibase/dialog/watermarkdialog.cxx
index 1246eabce4cc..6b993d22caf1 100644
--- a/sw/source/uibase/dialog/watermarkdialog.cxx
+++ b/sw/source/uibase/dialog/watermarkdialog.cxx
@@ -23,8 +23,6 @@ SwWatermarkDialog::SwWatermarkDialog( vcl::Window* pParent, SfxBindings& rBindin
 : ModelessDialog( pParent, "WatermarkDialog", "modules/swriter/ui/watermarkdialog.ui" )
 , m_rBindings( rBindings )
 {
-    get( m_pTextGrid, "TextGrid" );
-    get( m_pEnableWatermarkCB, "EnableWatermarkCB" );
     get( m_pTextInput, "TextInput" );
     get( m_pOKButton, "ok" );
     get( m_pFont, "FontBox" );
@@ -47,8 +45,6 @@ void SwWatermarkDialog::dispose()
     m_pAngle.clear();
     m_pTransparency.clear();
     m_pColor.clear();
-    m_pTextGrid.clear();
-    m_pEnableWatermarkCB.clear();
     m_pTextInput.clear();
     m_pOKButton.clear();
 
@@ -70,7 +66,6 @@ void SwWatermarkDialog::InitFields()
 
     m_pFont->Fill( pFontList );
 
-    m_pEnableWatermarkCB->SetClickHdl( LINK( this, SwWatermarkDialog, CheckBoxHdl ) );
     m_pOKButton->SetClickHdl( LINK( this, SwWatermarkDialog, OKButtonHdl ) );
 
     // Get watermark properties
@@ -81,7 +76,6 @@ void SwWatermarkDialog::InitFields()
     {
         const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>( pItem );
         OUString sText = pWatermark->GetText();
-        m_pEnableWatermarkCB->Check( !sText.isEmpty() );
         m_pTextInput->SetText( sText );
         m_pFont->SelectEntryPos( m_pFont->GetEntryPos( pWatermark->GetFont() ) );
         m_pAngle->SetValue( pWatermark->GetAngle() );
@@ -90,24 +84,9 @@ void SwWatermarkDialog::InitFields()
     }
 }
 
-void SwWatermarkDialog::Update()
-{
-    if( m_pEnableWatermarkCB->IsChecked() )
-        m_pTextGrid->Enable();
-    else
-        m_pTextGrid->Disable();
-}
-
-IMPL_LINK_NOARG( SwWatermarkDialog, CheckBoxHdl, Button*, void )
-{
-    Update();
-}
-
 IMPL_LINK_NOARG( SwWatermarkDialog, OKButtonHdl, Button*, void )
 {
-    OUString sText = "";
-    if( m_pEnableWatermarkCB->IsChecked() )
-        sText = m_pTextInput->GetText();
+    OUString sText = m_pTextInput->GetText();
 
     css::uno::Sequence<css::beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence(
     {
diff --git a/sw/source/uibase/inc/watermarkdialog.hxx b/sw/source/uibase/inc/watermarkdialog.hxx
index 7f59fe0a2bb7..b443fbce797d 100644
--- a/sw/source/uibase/inc/watermarkdialog.hxx
+++ b/sw/source/uibase/inc/watermarkdialog.hxx
@@ -23,16 +23,12 @@ public:
     virtual void dispose() override;
 
     void InitFields();
-    void Update();
 
 private:
-    DECL_LINK( CheckBoxHdl, Button*, void );
     DECL_LINK( OKButtonHdl, Button*, void );
 
     SfxBindings& m_rBindings;
 
-    VclPtr<VclGrid> m_pTextGrid;
-    VclPtr<CheckBox> m_pEnableWatermarkCB;
     VclPtr<Edit> m_pTextInput;
     VclPtr<PushButton> m_pOKButton;
     VclPtr<FontNameBox> m_pFont;
diff --git a/sw/uiconfig/swriter/ui/watermarkdialog.ui b/sw/uiconfig/swriter/ui/watermarkdialog.ui
index 316cd0c5d8bc..2edb38bf7f3a 100644
--- a/sw/uiconfig/swriter/ui/watermarkdialog.ui
+++ b/sw/uiconfig/swriter/ui/watermarkdialog.ui
@@ -62,7 +62,7 @@
             <property name="expand">False</property>
             <property name="fill">True</property>
             <property name="pack_type">end</property>
-            <property name="position">0</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
@@ -72,21 +72,6 @@
             <property name="orientation">vertical</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkCheckButton" id="EnableWatermarkCB">
-                <property name="label" translatable="yes">Insert watermark</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="xalign">0</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
               <object class="GtkGrid" id="TextGrid">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -210,14 +195,14 @@
               <packing>
                 <property name="expand">True</property>
                 <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="position">0</property>
               </packing>
             </child>
           </object>
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">0</property>
           </packing>
         </child>
       </object>
commit 489597d339af14a6403ee079bea35908112720ec
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Fri May 19 00:18:15 2017 +0200

    Watermark: extended configuration
    
    * it is possible to set font family,
      color, angle and transparency
    
    Change-Id: Idea2fb9ee748394bb3d706fa790e109238584cdb
    Reviewed-on: https://gerrit.libreoffice.org/37793
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index dbd8ab6ef39d..cfc59403d198 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -344,7 +344,10 @@
 #define SID_INSERT_FLOATINGFRAME            (SID_SFX_START + 563)
 #define SID_CLASSIFICATION_APPLY            (SID_SFX_START + 672)
 #define SID_WATERMARK                       (SID_SFX_START + 676)
-// FREE                                     (SID_SFX_START + 677)
+#define SID_WATERMARK_FONT                  (SID_SFX_START + 677)
+#define SID_WATERMARK_TRANSPARENCY          (SID_SFX_START + 805)
+#define SID_WATERMARK_COLOR                 (SID_SFX_START + 806)
+#define SID_WATERMARK_ANGLE                 (SID_SFX_START + 807)
 
 #define SID_HYPERLINK_DIALOG                (SID_SFX_START + 678)
 
@@ -411,9 +414,6 @@
 #define SID_PASTE_ONLY_TEXT                 (SID_SFX_START + 802)
 #define SID_PASTE_ONLY_FORMULA              (SID_SFX_START + 803)
 #define SID_PASTE_ONLY_VALUE                (SID_SFX_START + 804)
-    // FREE: SID_SFX_START + 805
-    // FREE: SID_SFX_START + 806
-    // FREE: SID_SFX_START + 807
     // FREE: SID_SFX_START + 808
     // FREE: SID_SFX_START + 809
     // FREE: SID_SFX_START + 810
diff --git a/include/sfx2/watermarkitem.hxx b/include/sfx2/watermarkitem.hxx
index 760aab3b0285..9fd7a91415a4 100644
--- a/include/sfx2/watermarkitem.hxx
+++ b/include/sfx2/watermarkitem.hxx
@@ -17,17 +17,29 @@ class SFX2_DLLPUBLIC SfxWatermarkItem: public SfxPoolItem
 public:
     static SfxPoolItem* CreateDefault();
     SfxWatermarkItem();
-    SfxWatermarkItem( sal_uInt16 nWhich, const OUString &rText );
     SfxWatermarkItem( const SfxWatermarkItem& );
     virtual SfxPoolItem*    Clone( SfxItemPool *pPool = nullptr ) const override;
     virtual bool            operator==( const SfxPoolItem& ) const override;
     virtual bool            QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
     virtual bool            PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
 
-    const OUString&         GetText() const { return m_aText; }
+    const OUString          GetText() const { return m_aText; }
+    void                    SetText(const OUString& aText) { m_aText = aText; }
+    const OUString          GetFont() const { return m_aFont; }
+    void                    SetFont(const OUString& aFont) { m_aFont = aFont; }
+    sal_Int16               GetAngle() const { return m_nAngle; }
+    void                    SetAngle(const sal_Int16 nAngle) { m_nAngle = nAngle; }
+    sal_Int16               GetTransparency() const { return m_nTransparency; }
+    void                    SetTransparency(const sal_Int16 nTransparency) { m_nTransparency = nTransparency; }
+    sal_uInt32              GetColor() const { return m_nColor; }
+    void                    SetColor(const sal_uInt32 nColor) { m_nColor = nColor; }
 
 private:
     OUString                m_aText;
+    OUString                m_aFont;
+    sal_Int16               m_nAngle;
+    sal_Int16               m_nTransparency;
+    sal_uInt32              m_nColor;
 };
 
 #endif
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 88735bbf9088..95d16d1588ee 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -4458,7 +4458,10 @@ SfxVoidItem ClassificationApply SID_CLASSIFICATION_APPLY
 ]
 
 SfxWatermarkItem Watermark SID_WATERMARK
-(SfxStringItem Text SID_WATERMARK)
+(SfxStringItem Text SID_WATERMARK, SfxStringItem Font SID_WATERMARK_FONT,
+ SfxInt16Item Angle SID_WATERMARK_ANGLE, SfxInt16Item Transparency SID_WATERMARK_TRANSPARENCY,
+ SfxUInt32Item Color SID_WATERMARK_COLOR
+)
 [
     AutoUpdate = FALSE,
     FastCall = FALSE,
diff --git a/sfx2/source/doc/watermarkitem.cxx b/sfx2/source/doc/watermarkitem.cxx
index 00c31f25d823..ebb794fcd73e 100644
--- a/sfx2/source/doc/watermarkitem.cxx
+++ b/sfx2/source/doc/watermarkitem.cxx
@@ -13,6 +13,10 @@
 SfxWatermarkItem::SfxWatermarkItem()
 : SfxPoolItem( SID_WATERMARK )
 , m_aText( "" )
+, m_aFont( "Liberation Sans" )
+, m_nAngle( 45 )
+, m_nTransparency( 50 )
+, m_nColor( 0xc0c0c0 )
 {
 }
 
@@ -21,22 +25,24 @@ SfxPoolItem* SfxWatermarkItem::CreateDefault()
     return new SfxWatermarkItem();
 }
 
-SfxWatermarkItem::SfxWatermarkItem( sal_uInt16 nWhichId, const OUString& rText )
-: SfxPoolItem( nWhichId )
-, m_aText( rText )
-{
-}
-
 SfxWatermarkItem::SfxWatermarkItem( const SfxWatermarkItem& rCopy )
 : SfxPoolItem( rCopy )
 , m_aText( rCopy.m_aText )
+, m_aFont( rCopy.m_aFont )
+, m_nAngle( rCopy.m_nAngle )
+, m_nTransparency( rCopy.m_nTransparency )
+, m_nColor( rCopy.m_nColor )
 {
 }
 
 bool SfxWatermarkItem::operator==( const SfxPoolItem& rCmp ) const
 {
     return ( SfxPoolItem::operator==( rCmp ) &&
-             m_aText == static_cast<const SfxWatermarkItem&>(rCmp).m_aText );
+             m_aText == static_cast<const SfxWatermarkItem&>(rCmp).m_aText &&
+             m_aFont == static_cast<const SfxWatermarkItem&>(rCmp).m_aFont &&
+             m_nAngle == static_cast<const SfxWatermarkItem&>(rCmp).m_nAngle &&
+             m_nTransparency == static_cast<const SfxWatermarkItem&>(rCmp).m_nTransparency &&
+             m_nColor == static_cast<const SfxWatermarkItem&>(rCmp).m_nColor );
 }
 
 SfxPoolItem* SfxWatermarkItem::Clone( SfxItemPool *) const
@@ -47,6 +53,10 @@ SfxPoolItem* SfxWatermarkItem::Clone( SfxItemPool *) const
 bool SfxWatermarkItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
 {
     rVal <<= m_aText;
+    rVal <<= m_aFont;
+    rVal <<= m_nAngle;
+    rVal <<= m_nTransparency;
+    rVal <<= m_nColor;
 
     return true;
 }
@@ -58,6 +68,10 @@ bool SfxWatermarkItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberI
     if ( rVal >>= aText )
     {
         m_aText = aText;
+        rVal >>= m_aFont;
+        rVal >>= m_nAngle;
+        rVal >>= m_nTransparency;
+        rVal >>= m_nColor;
         return true;
     }
 
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index db7a5346a586..e031303b6aae 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -367,7 +367,7 @@ public:
     void SetClassification(const OUString& rName, SfxClassificationPolicyType eType);
 
     SfxWatermarkItem GetWatermark();
-    void SetWatermark(const OUString& rText);
+    void SetWatermark(const SfxWatermarkItem& rText);
 
     void Insert2(SwField&, const bool bForceExpandHints);
 
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 029eb57be727..4f1967dc9648 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -229,7 +229,9 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli
                 }
             }
 
-            SetWatermark(aWatermark);
+            SfxWatermarkItem aWatermarkItem;
+            aWatermarkItem.SetText(aWatermark);
+            SetWatermark(aWatermarkItem);
         }
 
         if (bFooterIsNeeded)
@@ -260,7 +262,7 @@ SfxWatermarkItem SwEditShell::GetWatermark()
 {
     SwDocShell* pDocShell = GetDoc()->GetDocShell();
     if (!pDocShell)
-        return SfxWatermarkItem(SID_WATERMARK, "");
+        return SfxWatermarkItem();
 
     uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
     uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY);
@@ -286,14 +288,30 @@ SfxWatermarkItem SwEditShell::GetWatermark()
 
         if (xWatermark.is())
         {
+            SfxWatermarkItem aItem;
             uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY);
-            return SfxWatermarkItem(SID_WATERMARK, xTextRange->getString());
+            uno::Reference<beans::XPropertySet> xPropertySet(xWatermark, uno::UNO_QUERY);
+            sal_uInt32 nColor;
+            sal_Int16 nTransparency;
+            OUString aFont;
+
+            aItem.SetText(xTextRange->getString());
+
+            if (xPropertySet->getPropertyValue(UNO_NAME_CHAR_FONT_NAME) >>= aFont)
+                aItem.SetFont(aFont);
+            if (xPropertySet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= nColor)
+                aItem.SetColor(nColor);
+            // TODO: aItem.SetAngle(nAngle);
+            if (xPropertySet->getPropertyValue(UNO_NAME_FILL_TRANSPARENCE) >>= nTransparency)
+                aItem.SetTransparency(nTransparency);
+
+            return aItem;
         }
     }
-    return SfxWatermarkItem(SID_WATERMARK, "");
+    return SfxWatermarkItem();
 }
 
-void SwEditShell::SetWatermark(const OUString& rWatermark)
+void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark)
 {
     SwDocShell* pDocShell = GetDoc()->GetDocShell();
     if (!pDocShell)
@@ -326,12 +344,26 @@ void SwEditShell::SetWatermark(const OUString& rWatermark)
         static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
         uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
 
-        bool bDeleteWatermark = rWatermark.isEmpty();
+        bool bDeleteWatermark = rWatermark.GetText().isEmpty();
         if (xWatermark.is())
         {
+            sal_uInt32 nColor = 0xc0c0c0;
+            sal_Int16 nTransparency = 50;
+            OUString aFont = "";
+
+            uno::Reference<beans::XPropertySet> xPropertySet(xWatermark, uno::UNO_QUERY);
+            xPropertySet->getPropertyValue(UNO_NAME_CHAR_FONT_NAME) >>= aFont;
+            xPropertySet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= nColor;
+            // TODO: Angle
+            xPropertySet->getPropertyValue(UNO_NAME_FILL_TRANSPARENCE) >>= nTransparency;
+
             // 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() != rWatermark || bDeleteWatermark)
+            if (xTextRange->getString() != rWatermark.GetText()
+                || aFont != rWatermark.GetFont()
+                || nColor != rWatermark.GetColor()
+                || nTransparency != rWatermark.GetTransparency()
+                || bDeleteWatermark)
             {
                 // No: delete it and we'll insert a replacement.
                 uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY);
@@ -342,12 +374,18 @@ void SwEditShell::SetWatermark(const OUString& rWatermark)
 
         if (!xWatermark.is() && !bDeleteWatermark)
         {
+            OUString sFont = rWatermark.GetFont();
+            sal_Int16 nAngle = rWatermark.GetAngle();
+            sal_Int16 nTransparency = rWatermark.GetTransparency();
+            sal_uInt32 nColor = rWatermark.GetColor();
+
             // Calc the ratio.
             double fRatio = 0;
             OutputDevice* pOut = Application::GetDefaultDevice();
             vcl::Font aFont(pOut->GetFont());
+            aFont.SetFamilyName(sFont);
             fRatio = aFont.GetFontSize().Height();
-            fRatio /= pOut->GetTextWidth(rWatermark);
+            fRatio /= pOut->GetTextWidth(rWatermark.GetText());
 
             // Calc the size.
             sal_Int32 nWidth = 0;
@@ -378,7 +416,7 @@ void SwEditShell::SetWatermark(const OUString& rWatermark)
             basegfx::B2DHomMatrix aTransformation;
             aTransformation.identity();
             aTransformation.scale(nWidth, nHeight);
-            aTransformation.rotate(F_PI180 * -45);
+            aTransformation.rotate(F_PI180 * -1 * nAngle);
             drawing::HomogenMatrix3 aMatrix;
             aMatrix.Line1.Column1 = aTransformation.get(0, 0);
             aMatrix.Line1.Column2 = aTransformation.get(0, 1);
@@ -397,9 +435,9 @@ void SwEditShell::SetWatermark(const OUString& rWatermark)
             // 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_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(nColor)));
             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_FILL_TRANSPARENCE, uno::makeAny(nTransparency));
             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));
@@ -407,15 +445,15 @@ void SwEditShell::SetWatermark(const OUString& rWatermark)
             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_THROUGH));
+            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(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(sFont));
             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(rWatermark);
+            xTextRange->setString(rWatermark.GetText());
 
             uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
             xDefaulter->createCustomShapeDefaults("fontwork-plain-text");
diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx
index 7268c502230e..55db8a619643 100644
--- a/sw/source/uibase/app/docsh2.cxx
+++ b/sw/source/uibase/app/docsh2.cxx
@@ -57,6 +57,7 @@
 #include <svx/fmshell.hxx>
 #include <sfx2/linkmgr.hxx>
 #include <sfx2/classificationhelper.hxx>
+#include <sfx2/watermarkitem.hxx>
 
 #include <svtools/htmlcfg.hxx>
 #include <svx/ofaitem.hxx>
@@ -1167,8 +1168,19 @@ void SwDocShell::Execute(SfxRequest& rReq)
             {
                 if (pArgs && pArgs->GetItemState( SID_WATERMARK, false, &pItem ) == SfxItemState::SET)
                 {
-                    OUString aText = static_cast<const SfxStringItem*>( pItem )->GetValue();
-                    pSh->SetWatermark( aText );
+                    SfxWatermarkItem aItem;
+                    aItem.SetText( static_cast<const SfxStringItem*>( pItem )->GetValue() );
+
+                    if ( pArgs->GetItemState( SID_WATERMARK_FONT, false, &pItem ) == SfxItemState::SET )
+                        aItem.SetFont( static_cast<const SfxStringItem*>( pItem )->GetValue() );
+                    if ( pArgs->GetItemState( SID_WATERMARK_ANGLE, false, &pItem ) == SfxItemState::SET )
+                        aItem.SetAngle( static_cast<const SfxInt16Item*>( pItem )->GetValue() );
+                    if ( pArgs->GetItemState( SID_WATERMARK_TRANSPARENCY, false, &pItem ) == SfxItemState::SET )
+                        aItem.SetTransparency( static_cast<const SfxInt16Item*>( pItem )->GetValue() );
+                    if ( pArgs->GetItemState( SID_WATERMARK_COLOR, false, &pItem ) == SfxItemState::SET )
+                        aItem.SetColor( static_cast<const SfxUInt32Item*>( pItem )->GetValue() );
+
+                    pSh->SetWatermark( aItem );
                 }
                 else
                 {
diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx
index cffd2eca88ca..6eff974face6 100644
--- a/sw/source/uibase/app/docst.cxx
+++ b/sw/source/uibase/app/docst.cxx
@@ -276,10 +276,9 @@ void  SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
                 break;
             case SID_WATERMARK:
                 {
+                    SfxWatermarkItem aItem = pSh->GetWatermark();
                     if( pSh )
-                        rSet.Put(pSh->GetWatermark());
-
-                    rSet.InvalidateItem(nWhich);
+                        rSet.Put(aItem);
                 }
                 break;
             default:
diff --git a/sw/source/uibase/dialog/watermarkdialog.cxx b/sw/source/uibase/dialog/watermarkdialog.cxx
index bcc6077e9d03..1246eabce4cc 100644
--- a/sw/source/uibase/dialog/watermarkdialog.cxx
+++ b/sw/source/uibase/dialog/watermarkdialog.cxx
@@ -10,11 +10,14 @@
 #include <watermarkdialog.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/dispatchcommand.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/flstitem.hxx>
 #include <sfx2/sfxsids.hrc>
 #include <sfx2/bindings.hxx>
 #include <sfx2/dispatch.hxx>
 #include <svl/eitem.hxx>
 #include <sfx2/watermarkitem.hxx>
+#include <svtools/ctrltool.hxx>
 
 SwWatermarkDialog::SwWatermarkDialog( vcl::Window* pParent, SfxBindings& rBindings )
 : ModelessDialog( pParent, "WatermarkDialog", "modules/swriter/ui/watermarkdialog.ui" )
@@ -24,9 +27,10 @@ SwWatermarkDialog::SwWatermarkDialog( vcl::Window* pParent, SfxBindings& rBindin
     get( m_pEnableWatermarkCB, "EnableWatermarkCB" );
     get( m_pTextInput, "TextInput" );
     get( m_pOKButton, "ok" );
-
-    m_pEnableWatermarkCB->SetClickHdl( LINK( this, SwWatermarkDialog, CheckBoxHdl ) );
-    m_pOKButton->SetClickHdl( LINK( this, SwWatermarkDialog, OKButtonHdl ) );
+    get( m_pFont, "FontBox" );
+    get( m_pAngle, "Angle" );
+    get( m_pTransparency, "Transparency" );
+    get( m_pColor, "Color" );
 
     InitFields();
     Update();
@@ -39,6 +43,10 @@ SwWatermarkDialog::~SwWatermarkDialog()
 
 void SwWatermarkDialog::dispose()
 {
+    m_pFont.clear();
+    m_pAngle.clear();
+    m_pTransparency.clear();
+    m_pColor.clear();
     m_pTextGrid.clear();
     m_pEnableWatermarkCB.clear();
     m_pTextInput.clear();
@@ -49,14 +57,36 @@ void SwWatermarkDialog::dispose()
 
 void SwWatermarkDialog::InitFields()
 {
+    // Update font list
+    SfxObjectShell* pDocSh = SfxObjectShell::Current();
+    const SfxPoolItem* pFontItem;
+    const FontList* pFontList = nullptr;
+
+    if ( pDocSh && ( ( pFontItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ) ) != nullptr ) )
+        pFontList = static_cast<const SvxFontListItem*>( pFontItem )->GetFontList();
+
+    if(!pFontList)
+        pFontList = new FontList(Application::GetDefaultDevice(), nullptr);
+
+    m_pFont->Fill( pFontList );
+
+    m_pEnableWatermarkCB->SetClickHdl( LINK( this, SwWatermarkDialog, CheckBoxHdl ) );
+    m_pOKButton->SetClickHdl( LINK( this, SwWatermarkDialog, OKButtonHdl ) );
+
+    // Get watermark properties
     const SfxPoolItem* pItem;
     SfxItemState eState = m_rBindings.GetDispatcher()->QueryState( SID_WATERMARK, pItem );
 
-    if( eState >= SfxItemState::DEFAULT && pItem )
+    if( eState >= SfxItemState::DEFAULT && pItem && pItem->Which() == SID_WATERMARK)
     {
-        OUString sText = static_cast<const SfxWatermarkItem*>( pItem )->GetText();
+        const SfxWatermarkItem* pWatermark = static_cast<const SfxWatermarkItem*>( pItem );
+        OUString sText = pWatermark->GetText();
         m_pEnableWatermarkCB->Check( !sText.isEmpty() );
         m_pTextInput->SetText( sText );
+        m_pFont->SelectEntryPos( m_pFont->GetEntryPos( pWatermark->GetFont() ) );
+        m_pAngle->SetValue( pWatermark->GetAngle() );
+        m_pColor->SelectEntry( pWatermark->GetColor() );
+        m_pTransparency->SetValue( pWatermark->GetTransparency() );
     }
 }
 
@@ -81,7 +111,11 @@ IMPL_LINK_NOARG( SwWatermarkDialog, OKButtonHdl, Button*, void )
 
     css::uno::Sequence<css::beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence(
     {
-        { "Text", css::uno::makeAny( sText ) }
+        { "Text", css::uno::makeAny( sText ) },
+        { "Font", css::uno::makeAny( m_pFont->GetSelectEntry() ) },
+        { "Angle", css::uno::makeAny( static_cast<sal_Int16>( m_pAngle->GetValue() ) ) },
+        { "Transparency", css::uno::makeAny( static_cast<sal_Int16>( m_pTransparency->GetValue() ) ) },
+        { "Color", css::uno::makeAny( static_cast<sal_uInt32>( m_pColor->GetSelectEntryColor().GetRGBColor() ) ) }
     } ) );
     comphelper::dispatchCommand( ".uno:Watermark", aPropertyValues );
 
diff --git a/sw/source/uibase/inc/watermarkdialog.hxx b/sw/source/uibase/inc/watermarkdialog.hxx
index e1a60b96637d..7f59fe0a2bb7 100644
--- a/sw/source/uibase/inc/watermarkdialog.hxx
+++ b/sw/source/uibase/inc/watermarkdialog.hxx
@@ -10,7 +10,10 @@
 #define INCLUDED_SW_SOURCE_UIBASE_INC_WATERMARKDIALOG_HXX
 
 #include <sfx2/bindings.hxx>
+#include <vcl/field.hxx>
 #include <vcl/layout.hxx>
+#include <svtools/ctrlbox.hxx>
+#include <svx/colorbox.hxx>
 
 class SwWatermarkDialog : public ModelessDialog
 {
@@ -32,6 +35,10 @@ private:
     VclPtr<CheckBox> m_pEnableWatermarkCB;
     VclPtr<Edit> m_pTextInput;
     VclPtr<PushButton> m_pOKButton;
+    VclPtr<FontNameBox> m_pFont;
+    VclPtr<NumericField> m_pAngle;
+    VclPtr<NumericField> m_pTransparency;
+    VclPtr<SvxColorListBox> m_pColor;
 };
 
 #endif
diff --git a/sw/uiconfig/swriter/ui/watermarkdialog.ui b/sw/uiconfig/swriter/ui/watermarkdialog.ui
index f4d9b6377440..316cd0c5d8bc 100644
--- a/sw/uiconfig/swriter/ui/watermarkdialog.ui
+++ b/sw/uiconfig/swriter/ui/watermarkdialog.ui
@@ -2,6 +2,17 @@
 <!-- Generated with glade 3.20.0 -->
 <interface>
   <requires lib="gtk+" version="3.0"/>
+  <requires lib="LibreOffice" version="1.0"/>
+  <object class="GtkAdjustment" id="angle_adj">
+    <property name="upper">359</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="transparenct_adj">
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkDialog" id="WatermarkDialog">
     <property name="can_focus">False</property>
     <property name="border_width">6</property>
@@ -86,6 +97,7 @@
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">Text</property>
+                    <property name="xalign">0</property>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
@@ -103,6 +115,97 @@
                     <property name="top_attach">0</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="svtlo-FontNameBox" id="FontBox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="FontLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Font</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="AngleLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Angle</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="TransparencyLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Transparency</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="ColorLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Color</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="Angle">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="adjustment">angle_adj</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="Transparency">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="adjustment">transparenct_adj</property>
+                    <property name="value">50</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="svxcorelo-SvxColorListBox" id="Color">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">4</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -124,10 +227,4 @@
       <action-widget response="0">cancel</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkTextBuffer" id="textbuffer1">
-    <property name="text" translatable="yes">You did not specify a new name for the attachment.</property>
-  </object>
-  <object class="GtkTextBuffer" id="textbuffer2">
-    <property name="text" translatable="yes">If you would like to provide one, please type it now.</property>
-  </object>
 </interface>
commit abf39e521178e3438dc507167e18a24d160b3fd5
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Sun May 14 15:09:02 2017 +0200

    Watermark: Insert watermark command
    
    * added new command .uno:Watermark
    * if no arguments are provided the dialog
      is opened where user can enter the text
    * with provided Text argument the watermark
      is created
    * created SfxWatermarkItem to transfer
      watermark properties
    * dialog loads current setings
    * SetClassification use SetWatermark
    
    Change-Id: Ifc1319f5aa7c11bb141f8e4b5b9a5088613021c2
    Reviewed-on: https://gerrit.libreoffice.org/37599
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index aaa19884c0bc..dbd8ab6ef39d 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -343,7 +343,7 @@
 #define SID_INSERT_OBJECT                   (SID_SFX_START + 561)
 #define SID_INSERT_FLOATINGFRAME            (SID_SFX_START + 563)
 #define SID_CLASSIFICATION_APPLY            (SID_SFX_START + 672)
-// FREE                                     (SID_SFX_START + 676)
+#define SID_WATERMARK                       (SID_SFX_START + 676)
 // FREE                                     (SID_SFX_START + 677)
 
 #define SID_HYPERLINK_DIALOG                (SID_SFX_START + 678)
diff --git a/include/sfx2/watermarkitem.hxx b/include/sfx2/watermarkitem.hxx
new file mode 100644
index 000000000000..760aab3b0285
--- /dev/null
+++ b/include/sfx2/watermarkitem.hxx
@@ -0,0 +1,35 @@
+/* -*- 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/.
+ */
+#ifndef INCLUDED_SFX2_WATERMARKITEM_HXX
+#define INCLUDED_SFX2_WATERMARKITEM_HXX
+
+#include <sfx2/dllapi.h>
+#include <svl/poolitem.hxx>
+
+class SFX2_DLLPUBLIC SfxWatermarkItem: public SfxPoolItem
+{
+public:
+    static SfxPoolItem* CreateDefault();
+    SfxWatermarkItem();
+    SfxWatermarkItem( sal_uInt16 nWhich, const OUString &rText );
+    SfxWatermarkItem( const SfxWatermarkItem& );
+    virtual SfxPoolItem*    Clone( SfxItemPool *pPool = nullptr ) const override;
+    virtual bool            operator==( const SfxPoolItem& ) const override;
+    virtual bool            QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
+    virtual bool            PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
+
+    const OUString&         GetText() const { return m_aText; }
+
+private:
+    OUString                m_aText;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index 177ab9b26e8d..327a7dcd2ad8 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -2883,6 +2883,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:Watermark" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Watermark</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
     </node>
   </node>
 </oor:component-data>
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk
index 647078f5f500..17fd09f772dc 100644
--- a/sfx2/Library_sfx.mk
+++ b/sfx2/Library_sfx.mk
@@ -236,6 +236,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\
     sfx2/source/doc/syspath \
     sfx2/source/doc/zoomitem \
     sfx2/source/doc/templatedlg \
+    sfx2/source/doc/watermarkitem \
     sfx2/source/doc/saveastemplatedlg \
     sfx2/source/explorer/nochaos \
     sfx2/source/inet/inettbc \
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 0347532228af..88735bbf9088 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -4457,6 +4457,23 @@ SfxVoidItem ClassificationApply SID_CLASSIFICATION_APPLY
     GroupId = GID_DOCUMENT;
 ]
 
+SfxWatermarkItem Watermark SID_WATERMARK
+(SfxStringItem Text SID_WATERMARK)
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = GID_DOCUMENT;
+]
+
 SfxUInt16Item SwitchViewShell SID_VIEWSHELL
 
 [
diff --git a/sfx2/sdi/sfxitems.sdi b/sfx2/sdi/sfxitems.sdi
index ab1b3fd067e0..3a45c573ab1e 100644
--- a/sfx2/sdi/sfxitems.sdi
+++ b/sfx2/sdi/sfxitems.sdi
@@ -34,6 +34,7 @@
     item String     SfxObjectShellItem      //! Dummy
     item String     SfxUsrAnyItem           //! Dummy
     item String     SfxUnoFrameItem         //! Dummy
+    item String     SfxWatermarkItem        //! Dummy
 
     struct Point
     {
diff --git a/sfx2/source/doc/watermarkitem.cxx b/sfx2/source/doc/watermarkitem.cxx
new file mode 100644
index 000000000000..00c31f25d823
--- /dev/null
+++ b/sfx2/source/doc/watermarkitem.cxx
@@ -0,0 +1,67 @@
+/* -*- 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 <sfx2/watermarkitem.hxx>
+#include <sfx2/sfxsids.hrc>
+
+SfxWatermarkItem::SfxWatermarkItem()
+: SfxPoolItem( SID_WATERMARK )
+, m_aText( "" )
+{
+}
+
+SfxPoolItem* SfxWatermarkItem::CreateDefault()
+{
+    return new SfxWatermarkItem();
+}
+
+SfxWatermarkItem::SfxWatermarkItem( sal_uInt16 nWhichId, const OUString& rText )
+: SfxPoolItem( nWhichId )
+, m_aText( rText )
+{
+}
+
+SfxWatermarkItem::SfxWatermarkItem( const SfxWatermarkItem& rCopy )
+: SfxPoolItem( rCopy )
+, m_aText( rCopy.m_aText )
+{
+}
+
+bool SfxWatermarkItem::operator==( const SfxPoolItem& rCmp ) const
+{
+    return ( SfxPoolItem::operator==( rCmp ) &&
+             m_aText == static_cast<const SfxWatermarkItem&>(rCmp).m_aText );
+}
+
+SfxPoolItem* SfxWatermarkItem::Clone( SfxItemPool *) const
+{
+    return new SfxWatermarkItem(*this);
+}
+
+bool SfxWatermarkItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
+{
+    rVal <<= m_aText;
+
+    return true;
+}
+
+bool SfxWatermarkItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
+{
+    OUString aText;
+
+    if ( rVal >>= aText )
+    {
+        m_aText = aText;
+        return true;
+    }
+
+    return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 811c8c629ef6..2bffd7344fd7 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -588,6 +588,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/uibase/dialog/regionsw \
     sw/source/uibase/dialog/swabstdlg \
     sw/source/uibase/dialog/swwrtshitem \
+    sw/source/uibase/dialog/watermarkdialog \
     sw/source/uibase/dochdl/gloshdl \
     sw/source/uibase/dochdl/swdtflvr \
     sw/source/uibase/docvw/AnchorOverlayObject \
diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index 2ff017fe3b6a..e480f63f27e5 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -266,6 +266,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
 	sw/uiconfig/swriter/ui/viewoptionspage \
 	sw/uiconfig/swriter/ui/warndatasourcedialog \
 	sw/uiconfig/swriter/ui/warnemaildialog \
+	sw/uiconfig/swriter/ui/watermarkdialog \
 	sw/uiconfig/swriter/ui/wordcount \
 	sw/uiconfig/swriter/ui/wrapdialog \
 	sw/uiconfig/swriter/ui/wrappage \
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index c65d4e5df500..db7a5346a586 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -54,6 +54,7 @@ class CommandExtTextInputData;
 class SvNumberFormatter;
 class SfxPoolItem;
 class SfxItemSet;
+class SfxWatermarkItem;
 class SvxAutoCorrect;
 
 class SwField;
@@ -365,6 +366,9 @@ public:
 
     void SetClassification(const OUString& rName, SfxClassificationPolicyType eType);
 
+    SfxWatermarkItem GetWatermark();
+    void SetWatermark(const OUString& rText);
+
     void Insert2(SwField&, const bool bForceExpandHints);
 
     void UpdateFields( SwField & );   ///< One single field.
diff --git a/sw/sdi/_basesh.sdi b/sw/sdi/_basesh.sdi
index 1d3d1ae0f15f..b68ee48d55c3 100644
--- a/sw/sdi/_basesh.sdi
+++ b/sw/sdi/_basesh.sdi
@@ -372,6 +372,12 @@ interface BaseTextSelection
         StateMethod = StateStyle ;
     ]
 
+    SID_WATERMARK
+    [
+        ExecMethod = Execute ;
+        StateMethod = StateStyle ;
+    ]
+
      //OS: Selection.Escape gibt es zusaetzlich zu Window.Escape
 
     FN_ESCAPE // status(final|play|rec)
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 5277af00a11b..029eb57be727 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -58,6 +58,7 @@
 #include <unoprnms.hxx>
 #include <rootfrm.hxx>
 #include <pagefrm.hxx>
+#include <sfx2/watermarkitem.hxx>
 
 namespace
 {
@@ -228,127 +229,7 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli
                 }
             }
 
-            if (bWatermarkIsNeeded || bHadWatermark)
-            {
-                OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
-                static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
-                uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
-
-                bool bDeleteWatermark = bHadWatermark && !bWatermarkIsNeeded;
-                if (xWatermark.is())
-                {
-                    // 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 || bDeleteWatermark)
-                    {
-                        // No: delete it and we'll insert a replacement.
-                        uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY);
-                        xComponent->dispose();
-                        xWatermark.clear();
-                    }
-                }
-
-                if (!xWatermark.is() && bWatermarkIsNeeded)
-                {
-                    // 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_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK());
-                    xLockable->removeActionLock();
-                }
-            }
+            SetWatermark(aWatermark);
         }
 
         if (bFooterIsNeeded)
@@ -375,6 +256,193 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli
     }
 }
 
+SfxWatermarkItem SwEditShell::GetWatermark()
+{
+    SwDocShell* pDocShell = GetDoc()->GetDocShell();
+    if (!pDocShell)
+        return SfxWatermarkItem(SID_WATERMARK, "");
+
+    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<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
+        uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
+
+        bool bHeaderIsOn = false;
+        xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
+        if (!bHeaderIsOn)
+            xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
+
+        uno::Reference<text::XText> xHeaderText;
+        xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
+
+        OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
+        static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
+        uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
+
+        if (xWatermark.is())
+        {
+            uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY);
+            return SfxWatermarkItem(SID_WATERMARK, xTextRange->getString());
+        }
+    }
+    return SfxWatermarkItem(SID_WATERMARK, "");
+}
+
+void SwEditShell::SetWatermark(const OUString& rWatermark)
+{
+    SwDocShell* pDocShell = GetDoc()->GetDocShell();
+    if (!pDocShell)
+        return;
+
+    SfxClassificationHelper aHelper(pDocShell->getDocProperties());
+
+    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<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
+        uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
+
+        // 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;
+
+        OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
+        static const OUString sWatermark = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK();
+        uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, sWatermark);
+
+        bool bDeleteWatermark = rWatermark.isEmpty();
+        if (xWatermark.is())
+        {
+            // 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() != rWatermark || bDeleteWatermark)
+            {
+                // No: delete it and we'll insert a replacement.
+                uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY);
+                xComponent->dispose();
+                xWatermark.clear();
+            }
+        }
+
+        if (!xWatermark.is() && !bDeleteWatermark)
+        {
+            // Calc the ratio.
+            double fRatio = 0;
+            OutputDevice* pOut = Application::GetDefaultDevice();
+            vcl::Font aFont(pOut->GetFont());
+            fRatio = aFont.GetFontSize().Height();
+            fRatio /= pOut->GetTextWidth(rWatermark);
+
+            // 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_THROUGH));
+            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(rWatermark);
+
+            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_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCWATERMARK());
+            xLockable->removeActionLock();
+        }
+    }
+}
+
 // #i62675#
 void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat,
                                 const bool bResetListAttrs)
diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx
index 4198d18ec46b..7268c502230e 100644
--- a/sw/source/uibase/app/docsh2.cxx
+++ b/sw/source/uibase/app/docsh2.cxx
@@ -124,6 +124,7 @@
 
 #include "dialog.hrc"
 #include "swabstdlg.hxx"
+#include "watermarkdialog.hxx"
 
 #include <ndtxt.hxx>
 
@@ -1159,6 +1160,27 @@ void SwDocShell::Execute(SfxRequest& rReq)
                 SAL_WARN("sw.ui", "missing parameter for SID_CLASSIFICATION_APPLY");
         }
         break;
+        case SID_WATERMARK:
+        {
+            SwWrtShell* pSh = GetWrtShell();
+            if ( pSh )
+            {
+                if (pArgs && pArgs->GetItemState( SID_WATERMARK, false, &pItem ) == SfxItemState::SET)
+                {
+                    OUString aText = static_cast<const SfxStringItem*>( pItem )->GetValue();
+                    pSh->SetWatermark( aText );
+                }
+                else
+                {
+                    SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current();
+                    SfxBindings& rBindings( pViewShell->GetViewFrame()->GetBindings() );
+                    ScopedVclPtr<SwWatermarkDialog> pDlg( VclPtr<SwWatermarkDialog>::Create( nullptr, rBindings ) );
+                    pDlg->Execute();
+                    pDlg.disposeAndClear();
+                }
+            }
+        }
+        break;
         case SID_NOTEBOOKBAR:
         {
             const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx
index ee02b382a861..cffd2eca88ca 100644
--- a/sw/source/uibase/app/docst.cxx
+++ b/sw/source/uibase/app/docst.cxx
@@ -85,6 +85,7 @@
 #include <list.hxx>
 #include <paratr.hxx>
 #include <tblafmt.hxx>
+#include <sfx2/watermarkitem.hxx>
 
 extern bool g_bNoInterrupt;       // in swmodule.cxx
 
@@ -273,6 +274,14 @@ void  SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
                 // Just trigger ClassificationCategoriesController::statusChanged().
                 rSet.InvalidateItem(nWhich);
                 break;
+            case SID_WATERMARK:
+                {
+                    if( pSh )
+                        rSet.Put(pSh->GetWatermark());
+
+                    rSet.InvalidateItem(nWhich);
+                }
+                break;
             default:
                 OSL_FAIL("Invalid SlotId");
         }
diff --git a/sw/source/uibase/dialog/watermarkdialog.cxx b/sw/source/uibase/dialog/watermarkdialog.cxx
new file mode 100644
index 000000000000..bcc6077e9d03
--- /dev/null
+++ b/sw/source/uibase/dialog/watermarkdialog.cxx
@@ -0,0 +1,91 @@
+/* -*- 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 <watermarkdialog.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/dispatchcommand.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/watermarkitem.hxx>
+
+SwWatermarkDialog::SwWatermarkDialog( vcl::Window* pParent, SfxBindings& rBindings )
+: ModelessDialog( pParent, "WatermarkDialog", "modules/swriter/ui/watermarkdialog.ui" )
+, m_rBindings( rBindings )
+{
+    get( m_pTextGrid, "TextGrid" );
+    get( m_pEnableWatermarkCB, "EnableWatermarkCB" );
+    get( m_pTextInput, "TextInput" );
+    get( m_pOKButton, "ok" );
+
+    m_pEnableWatermarkCB->SetClickHdl( LINK( this, SwWatermarkDialog, CheckBoxHdl ) );
+    m_pOKButton->SetClickHdl( LINK( this, SwWatermarkDialog, OKButtonHdl ) );
+
+    InitFields();
+    Update();
+}
+
+SwWatermarkDialog::~SwWatermarkDialog()
+{
+    disposeOnce();
+}
+
+void SwWatermarkDialog::dispose()
+{
+    m_pTextGrid.clear();
+    m_pEnableWatermarkCB.clear();
+    m_pTextInput.clear();
+    m_pOKButton.clear();
+
+    ModelessDialog::dispose();
+}
+
+void SwWatermarkDialog::InitFields()
+{
+    const SfxPoolItem* pItem;
+    SfxItemState eState = m_rBindings.GetDispatcher()->QueryState( SID_WATERMARK, pItem );
+
+    if( eState >= SfxItemState::DEFAULT && pItem )
+    {
+        OUString sText = static_cast<const SfxWatermarkItem*>( pItem )->GetText();
+        m_pEnableWatermarkCB->Check( !sText.isEmpty() );
+        m_pTextInput->SetText( sText );
+    }
+}
+
+void SwWatermarkDialog::Update()
+{
+    if( m_pEnableWatermarkCB->IsChecked() )
+        m_pTextGrid->Enable();
+    else
+        m_pTextGrid->Disable();
+}
+
+IMPL_LINK_NOARG( SwWatermarkDialog, CheckBoxHdl, Button*, void )
+{
+    Update();
+}
+
+IMPL_LINK_NOARG( SwWatermarkDialog, OKButtonHdl, Button*, void )
+{
+    OUString sText = "";
+    if( m_pEnableWatermarkCB->IsChecked() )
+        sText = m_pTextInput->GetText();
+
+    css::uno::Sequence<css::beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence(
+    {
+        { "Text", css::uno::makeAny( sText ) }
+    } ) );
+    comphelper::dispatchCommand( ".uno:Watermark", aPropertyValues );
+
+    Close();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/watermarkdialog.hxx b/sw/source/uibase/inc/watermarkdialog.hxx
new file mode 100644
index 000000000000..e1a60b96637d
--- /dev/null
+++ b/sw/source/uibase/inc/watermarkdialog.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WATERMARKDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WATERMARKDIALOG_HXX
+
+#include <sfx2/bindings.hxx>
+#include <vcl/layout.hxx>
+
+class SwWatermarkDialog : public ModelessDialog
+{
+public:
+    SwWatermarkDialog( vcl::Window* pParent, SfxBindings& rBindings );
+    virtual ~SwWatermarkDialog() override;
+    virtual void dispose() override;
+
+    void InitFields();
+    void Update();
+
+private:
+    DECL_LINK( CheckBoxHdl, Button*, void );
+    DECL_LINK( OKButtonHdl, Button*, void );
+
+    SfxBindings& m_rBindings;
+
+    VclPtr<VclGrid> m_pTextGrid;
+    VclPtr<CheckBox> m_pEnableWatermarkCB;
+    VclPtr<Edit> m_pTextInput;
+    VclPtr<PushButton> m_pOKButton;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index 3127b1f25beb..9da444b3d081 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -959,6 +959,11 @@ void SwBaseShell::Execute(SfxRequest &rReq)
             GetView().GetDocShell()->Execute(rReq);
         }
         break;
+        case SID_WATERMARK:
+        {
+            GetView().GetDocShell()->Execute(rReq);
+        }
+        break;
         case FN_ESCAPE:
             GetView().ExecuteSlot(rReq);
         break;
diff --git a/sw/source/uibase/shells/slotadd.cxx b/sw/source/uibase/shells/slotadd.cxx
index c0658a329e51..39b4df4b6896 100644
--- a/sw/source/uibase/shells/slotadd.cxx
+++ b/sw/source/uibase/shells/slotadd.cxx
@@ -40,6 +40,7 @@
 #include <svx/pageitem.hxx>
 #include <svl/srchitem.hxx>
 #include <sfx2/tplpitem.hxx>
+#include <sfx2/watermarkitem.hxx>
 #include <editeng/wrlmitem.hxx>
 #include <editeng/protitem.hxx>
 #include <editeng/opaqitem.hxx>
diff --git a/sw/uiconfig/swriter/toolbar/classificationbar.xml b/sw/uiconfig/swriter/toolbar/classificationbar.xml
index 3ee34071e040..01981333a46e 100644
--- a/sw/uiconfig/swriter/toolbar/classificationbar.xml
+++ b/sw/uiconfig/swriter/toolbar/classificationbar.xml
@@ -9,4 +9,5 @@
 -->
 <toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink" toolbar:id="toolbar">
   <toolbar:toolbaritem xlink:href=".uno:ClassificationApply"/>
+  <toolbar:toolbaritem xlink:href=".uno:Watermark"/>
 </toolbar:toolbar>
diff --git a/sw/uiconfig/swriter/ui/watermarkdialog.ui b/sw/uiconfig/swriter/ui/watermarkdialog.ui
new file mode 100644
index 000000000000..f4d9b6377440
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/watermarkdialog.ui
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+  <requires lib="gtk+" version="3.0"/>
+  <object class="GtkDialog" id="WatermarkDialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">6</property>
+    <property name="title" translatable="yes">Watermark</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">24</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="Box">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkCheckButton" id="EnableWatermarkCB">
+                <property name="label" translatable="yes">Insert watermark</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="xalign">0</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="TextGrid">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="TextLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Text</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="TextInput">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list