diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2017-05-14 15:09:02 +0200 |
---|---|---|
committer | Szymon Kłos <szymon.klos@collabora.com> | 2017-05-31 21:50:58 +0200 |
commit | abf39e521178e3438dc507167e18a24d160b3fd5 (patch) | |
tree | 0a65eb59b77303e76f81f47fbc7e3db121bc0135 | |
parent | 115577b1c3cf42f4831d79be41f512fa21383832 (diff) |
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@libreoffice.org>
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
-rw-r--r-- | include/sfx2/sfxsids.hrc | 2 | ||||
-rw-r--r-- | include/sfx2/watermarkitem.hxx | 35 | ||||
-rw-r--r-- | officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu | 8 | ||||
-rw-r--r-- | sfx2/Library_sfx.mk | 1 | ||||
-rw-r--r-- | sfx2/sdi/sfx.sdi | 17 | ||||
-rw-r--r-- | sfx2/sdi/sfxitems.sdi | 1 | ||||
-rw-r--r-- | sfx2/source/doc/watermarkitem.cxx | 67 | ||||
-rw-r--r-- | sw/Library_sw.mk | 1 | ||||
-rw-r--r-- | sw/UIConfig_swriter.mk | 1 | ||||
-rw-r--r-- | sw/inc/editsh.hxx | 4 | ||||
-rw-r--r-- | sw/sdi/_basesh.sdi | 6 | ||||
-rw-r--r-- | sw/source/core/edit/edfcol.cxx | 310 | ||||
-rw-r--r-- | sw/source/uibase/app/docsh2.cxx | 22 | ||||
-rw-r--r-- | sw/source/uibase/app/docst.cxx | 9 | ||||
-rw-r--r-- | sw/source/uibase/dialog/watermarkdialog.cxx | 91 | ||||
-rw-r--r-- | sw/source/uibase/inc/watermarkdialog.hxx | 39 | ||||
-rw-r--r-- | sw/source/uibase/shells/basesh.cxx | 5 | ||||
-rw-r--r-- | sw/source/uibase/shells/slotadd.cxx | 1 | ||||
-rw-r--r-- | sw/uiconfig/swriter/toolbar/classificationbar.xml | 1 | ||||
-rw-r--r-- | sw/uiconfig/swriter/ui/watermarkdialog.ui | 133 |
20 files changed, 632 insertions, 122 deletions
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> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">ok</action-widget> + <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> |