diff options
25 files changed, 680 insertions, 1047 deletions
diff --git a/include/svx/annotation/Annotation.hxx b/include/svx/annotation/Annotation.hxx index be378d6a61de..4001d97f406f 100644 --- a/include/svx/annotation/Annotation.hxx +++ b/include/svx/annotation/Annotation.hxx @@ -41,6 +41,34 @@ SVXCORE_DLLPUBLIC void LOKCommentNotify(CommentNotificationType nType, const SfxViewShell* pViewShell, Annotation& rAnnotation); SVXCORE_DLLPUBLIC void LOKCommentNotifyAll(CommentNotificationType nType, Annotation& rAnnotation); +enum class AnnotationType +{ + None, + Square, + Polygon, + Circle, + Ink, + Highlight, + Line, + FreeText, +}; + +struct CreationInfo +{ + AnnotationType meType = AnnotationType::None; + + std::vector<basegfx::B2DPolygon> maPolygons; + basegfx::B2DRectangle maRectangle; + + float mnWidth = 0.0f; + + bool mbFillColor = false; + Color maFillColor = COL_TRANSPARENT; + + bool mbColor = false; + Color maColor = COL_TRANSPARENT; +}; + struct SVXCORE_DLLPUBLIC AnnotationData { css::geometry::RealPoint2D m_Position; @@ -73,7 +101,7 @@ protected: css::util::DateTime m_DateTime; rtl::Reference<sdr::annotation::TextApiObject> m_TextRange; - bool m_bIsFreeText = false; + CreationInfo maCreationInfo; std::unique_ptr<SdrUndoAction> createUndoAnnotation(); @@ -125,9 +153,8 @@ public: sal_uInt32 GetId() const { return m_nId; } - void setIsFreeText(bool value) { m_bIsFreeText = value; } - - bool isFreeText() const { return m_bIsFreeText; } + CreationInfo const& getCreationInfo() { return maCreationInfo; } + void setCreationInfo(CreationInfo const& rCreationInfo) { maCreationInfo = rCreationInfo; } }; typedef std::vector<rtl::Reference<Annotation>> AnnotationVector; diff --git a/include/svx/annotation/AnnotationObject.hxx b/include/svx/annotation/AnnotationObject.hxx new file mode 100644 index 000000000000..d46f4e7c3150 --- /dev/null +++ b/include/svx/annotation/AnnotationObject.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <svx/svxdllapi.h> + +#include <svx/annotation/Annotation.hxx> +#include <svx/svdorect.hxx> + +namespace sdr::annotation +{ +struct SVXCORE_DLLPUBLIC AnnotationViewData +{ + sal_Int32 nIndex = -1; + sal_uInt16 nAuthorIndex = 0; +}; + +class SVXCORE_DLLPUBLIC AnnotationObject final : public SdrRectObj +{ +private: + virtual ~AnnotationObject() override; + + sdr::annotation::AnnotationViewData maViewData; + +public: + AnnotationObject(SdrModel& rSdrModel); + AnnotationObject(SdrModel& rSdrModel, AnnotationObject const& rSource); + AnnotationObject(SdrModel& rSdrModel, tools::Rectangle const& rRectangle, + sdr::annotation::AnnotationViewData const& aAnnotationViewData); + + rtl::Reference<SdrObject> CloneSdrObject(SdrModel& rTargetModel) const override; + + SdrObjKind GetObjIdentifier() const override; + OUString TakeObjNameSingul() const override; + OUString TakeObjNamePlural() const override; + + void TakeObjInfo(SdrObjTransformInfoRec& rInfo) const override; + + void ApplyAnnotationName(); + + bool HasTextEdit() const override; + + bool hasSpecialDrag() const override { return true; } + + bool beginSpecialDrag(SdrDragStat& /*rDrag*/) const override { return false; } +}; + +} // end sdr::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/svdobjkind.hxx b/include/svx/svdobjkind.hxx index d25eba0a0027..1517bbeba4aa 100644 --- a/include/svx/svdobjkind.hxx +++ b/include/svx/svdobjkind.hxx @@ -53,6 +53,7 @@ enum class SdrObjKind : sal_uInt16 CustomShape = 33, /// custom shape Media = 34, /// media shape Table = 35, /// table + Annotation = 36, /// annotation object OLE2Applet = 100, OLE2Plugin = 101, diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index 01f3a1d59610..5da9c10b2adf 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -212,7 +212,6 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/animations/SlideTransitionPane \ sd/source/ui/animations/motionpathtag \ sd/source/ui/annotations/annotationmanager \ - sd/source/ui/annotations/annotationtag \ sd/source/ui/annotations/annotationwindow \ sd/source/ui/app/optsitem \ sd/source/ui/app/sddll \ diff --git a/sd/UIConfig_sdraw.mk b/sd/UIConfig_sdraw.mk index a84f0f286cae..276a1efc5cd8 100644 --- a/sd/UIConfig_sdraw.mk +++ b/sd/UIConfig_sdraw.mk @@ -17,6 +17,7 @@ $(eval $(call gb_UIConfig_add_popupmenufiles,modules/sdraw,\ sd/uiconfig/sdraw/popupmenu/3dobject \ sd/uiconfig/sdraw/popupmenu/3dscene2 \ sd/uiconfig/sdraw/popupmenu/3dscene \ + sd/uiconfig/sdraw/popupmenu/annotation \ sd/uiconfig/sdraw/popupmenu/bezier \ sd/uiconfig/sdraw/popupmenu/connector \ sd/uiconfig/sdraw/popupmenu/curve \ diff --git a/sd/UIConfig_simpress.mk b/sd/UIConfig_simpress.mk index ee778eaeb91a..c70fc3bc9cb3 100644 --- a/sd/UIConfig_simpress.mk +++ b/sd/UIConfig_simpress.mk @@ -17,6 +17,7 @@ $(eval $(call gb_UIConfig_add_popupmenufiles,modules/simpress,\ sd/uiconfig/simpress/popupmenu/3dobject \ sd/uiconfig/simpress/popupmenu/3dscene2 \ sd/uiconfig/simpress/popupmenu/3dscene \ + sd/uiconfig/simpress/popupmenu/annotation \ sd/uiconfig/simpress/popupmenu/bezier \ sd/uiconfig/simpress/popupmenu/connector \ sd/uiconfig/simpress/popupmenu/curve \ diff --git a/sd/inc/Annotation.hxx b/sd/inc/Annotation.hxx index aba2d27d77b7..8d9f34501e0d 100644 --- a/sd/inc/Annotation.hxx +++ b/sd/inc/Annotation.hxx @@ -46,17 +46,10 @@ namespace sd { rtl::Reference<sdr::annotation::Annotation> createAnnotation(SdPage* pPage); +rtl::Reference<sdr::annotation::Annotation> createAnnotationAndAddToPage(SdPage* pPage); std::unique_ptr<SdrUndoAction> CreateUndoInsertOrRemoveAnnotation(rtl::Reference<sdr::annotation::Annotation>& xAnnotation, bool bInsert); -struct SD_DLLPUBLIC CustomAnnotationMarker -{ - Color maLineColor; - Color maFillColor; - float mnLineWidth; - std::vector<basegfx::B2DPolygon> maPolygons; -}; - class SAL_DLLPUBLIC_RTTI Annotation final : public sdr::annotation::Annotation { public: @@ -90,25 +83,8 @@ public: void createChangeUndo(); - void createCustomAnnotationMarker() - { - m_pCustomAnnotationMarker = std::make_unique<CustomAnnotationMarker>(); - } - - CustomAnnotationMarker& getCustomAnnotationMarker() - { - return *m_pCustomAnnotationMarker; - } - - bool hasCustomAnnotationMarker() const - { - return bool(m_pCustomAnnotationMarker); - } - private: void createChangeUndoImpl(std::unique_lock<std::mutex>& g); - - std::unique_ptr<CustomAnnotationMarker> m_pCustomAnnotationMarker; }; } diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index 67e4ef2a1f4e..2b2bdb7a9c56 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -1808,7 +1808,7 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeImpress) CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty()); CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 282, 282"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); // Edit this annotation now aArgs = comphelper::InitPropertySequence( @@ -1821,7 +1821,7 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeImpress) CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action")); CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); + CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 282, 282"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); comphelper::LibreOfficeKit::setTiledAnnotations(true); } @@ -1854,7 +1854,7 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeDraw) CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty()); CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 282, 282"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); // Edit this annotation now aArgs = comphelper::InitPropertySequence( @@ -1867,7 +1867,7 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeDraw) CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action")); CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); + CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 282, 282"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle")); comphelper::LibreOfficeKit::setTiledAnnotations(true); } diff --git a/sd/source/core/annotations/Annotation.cxx b/sd/source/core/annotations/Annotation.cxx index 44fe5397e456..f41b1507cf72 100644 --- a/sd/source/core/annotations/Annotation.cxx +++ b/sd/source/core/annotations/Annotation.cxx @@ -61,9 +61,14 @@ protected: } -rtl::Reference<sdr::annotation::Annotation> createAnnotation(SdPage* pPage ) +rtl::Reference<sdr::annotation::Annotation> createAnnotation(SdPage* pPage) { - rtl::Reference<Annotation> xAnnotation(new Annotation(comphelper::getProcessComponentContext(), pPage)); + return rtl::Reference<Annotation>(new Annotation(comphelper::getProcessComponentContext(), pPage)); +} + +rtl::Reference<sdr::annotation::Annotation> createAnnotationAndAddToPage(SdPage* pPage) +{ + rtl::Reference<sdr::annotation::Annotation> xAnnotation = createAnnotation(pPage); pPage->addAnnotation(xAnnotation, -1); return xAnnotation; } @@ -268,7 +273,7 @@ void UndoInsertOrRemoveAnnotation::Undo() if (mbInsert) { - pPage->removeAnnotation(mxAnnotation); + pPage->removeAnnotationNoNotify(mxAnnotation); } else { @@ -286,12 +291,12 @@ void UndoInsertOrRemoveAnnotation::Redo() if (mbInsert) { - pPage->addAnnotation(mxAnnotation, mnIndex); + pPage->addAnnotationNoNotify(mxAnnotation, mnIndex); LOKCommentNotifyAll(sdr::annotation::CommentNotificationType::Add, *mxAnnotation); } else { - pPage->removeAnnotation(mxAnnotation); + pPage->removeAnnotationNoNotify(mxAnnotation); } } diff --git a/sd/source/core/sdpage2.cxx b/sd/source/core/sdpage2.cxx index 915ed33e75a6..620871e1cae8 100644 --- a/sd/source/core/sdpage2.cxx +++ b/sd/source/core/sdpage2.cxx @@ -45,6 +45,7 @@ #include <DrawDocShell.hxx> #include <svl/itemset.hxx> +#include <svx/annotation/ObjectAnnotationData.hxx> using namespace ::sd; using namespace ::com::sun::star; @@ -389,6 +390,7 @@ void SdPage::lateInit(const SdPage& rSrcPage) uno::Reference<css::text::XTextCopy> xRange (aNewAnnotation->getTextRange(), uno::UNO_QUERY); if(xSourceRange.is() && xRange.is()) xRange->copyText(xSourceRange); + addAnnotation(aNewAnnotation, -1); } // fix user calls for duplicated slide @@ -612,6 +614,15 @@ void SdPage::removeAnnotationNoNotify(rtl::Reference<sdr::annotation::Annotation rModel.AddUndo(std::move(pAction)); } + for (size_t nObjectIndex = 0; nObjectIndex < GetObjCount(); ++nObjectIndex) + { + SdrObject* pObject = GetObj(nObjectIndex); + if (pObject->isAnnotationObject() && pObject->getAnnotationData()->mxAnnotation == xAnnotation) + { + RemoveObject(nObjectIndex); + } + } + auto iterator = std::find(maAnnotations.begin(), maAnnotations.end(), xAnnotation); if (iterator != maAnnotations.end()) maAnnotations.erase(iterator); diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx index 89ff0dd134db..6b69530454c3 100644 --- a/sd/source/filter/pdf/sdpdffilter.cxx +++ b/sd/source/filter/pdf/sdpdffilter.cxx @@ -83,8 +83,10 @@ bool SdPdfFilter::Import() // Make the page size match the rendered image. pPage->SetSize(aSizeHMM); - rtl::Reference<SdrGrafObj> pSdrGrafObj = new SdrGrafObj( - pPage->getSdrModelFromSdrPage(), rGraphic, tools::Rectangle(Point(), aSizeHMM)); + SdrModel& rModel = pPage->getSdrModelFromSdrPage(); + + rtl::Reference<SdrGrafObj> pSdrGrafObj + = new SdrGrafObj(rModel, rGraphic, tools::Rectangle(Point(), aSizeHMM)); pSdrGrafObj->SetResizeProtect(true); pSdrGrafObj->SetMoveProtect(true); @@ -101,97 +103,118 @@ bool SdPdfFilter::Import() xText->setString(rPDFAnnotation.maText); // position is in mm not 100thmm geometry::RealPoint2D aUnoPosition(rPDFAnnotation.maRectangle.getMinX() / 100.0, - rPDFAnnotation.maRectangle.getMinY() / 100.00); + rPDFAnnotation.maRectangle.getMinY() / 100.0); geometry::RealSize2D aUnoSize(rPDFAnnotation.maRectangle.getWidth() / 100.0, - rPDFAnnotation.maRectangle.getHeight() / 100.00); + rPDFAnnotation.maRectangle.getHeight() / 100.0); xAnnotation->setPosition(aUnoPosition); xAnnotation->setSize(aUnoSize); xAnnotation->setDateTime(rPDFAnnotation.maDateTime); if (rPDFAnnotation.mpMarker) { - auto* pAnnotation = static_cast<sd::Annotation*>(xAnnotation.get()); - pAnnotation->createCustomAnnotationMarker(); - sd::CustomAnnotationMarker& rCustomAnnotationMarker - = pAnnotation->getCustomAnnotationMarker(); - - rCustomAnnotationMarker.maLineColor = rPDFAnnotation.maColor; + sdr::annotation::CreationInfo aInfo; + aInfo.maRectangle = rPDFAnnotation.maRectangle; if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Polygon) { + aInfo.meType = sdr::annotation::AnnotationType::Polygon; + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerPolygon*>( rPDFAnnotation.mpMarker.get()); - rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; - rCustomAnnotationMarker.maFillColor = pMarker->maFillColor; - rCustomAnnotationMarker.maPolygons.push_back(pMarker->maPolygon); + + aInfo.maPolygons.push_back(pMarker->maPolygon); + aInfo.mnWidth = pMarker->mnWidth; + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.mbColor = true; + aInfo.maFillColor = pMarker->maFillColor; + aInfo.mbFillColor = true; } else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Square) { + aInfo.meType = sdr::annotation::AnnotationType::Square; + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerSquare*>( rPDFAnnotation.mpMarker.get()); - basegfx::B2DPolygon aPoly - = basegfx::utils::createPolygonFromRect(rPDFAnnotation.maRectangle); - rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; - rCustomAnnotationMarker.maFillColor = pMarker->maFillColor; - rCustomAnnotationMarker.maPolygons.push_back(aPoly); + + aInfo.mnWidth = pMarker->mnWidth; + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.mbColor = true; + aInfo.maFillColor = pMarker->maFillColor; + aInfo.mbFillColor = true; } else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Circle) { + aInfo.meType = sdr::annotation::AnnotationType::Circle; + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerCircle*>( rPDFAnnotation.mpMarker.get()); - basegfx::B2DPoint rCenter = rPDFAnnotation.maRectangle.getCenter(); - double fRadiusX = rPDFAnnotation.maRectangle.getWidth() / 2; - double fRadiusY = rPDFAnnotation.maRectangle.getHeight() / 2; - - basegfx::B2DPolygon aPoly - = basegfx::utils::createPolygonFromEllipse(rCenter, fRadiusX, fRadiusY); - rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; - rCustomAnnotationMarker.maFillColor = pMarker->maFillColor; - rCustomAnnotationMarker.maPolygons.push_back(aPoly); + aInfo.mnWidth = pMarker->mnWidth; + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.mbColor = true; + aInfo.maFillColor = pMarker->maFillColor; + aInfo.mbFillColor = true; } else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Ink) { + aInfo.meType = sdr::annotation::AnnotationType::Ink; + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerInk*>( rPDFAnnotation.mpMarker.get()); - rCustomAnnotationMarker.maPolygons.insert( - rCustomAnnotationMarker.maPolygons.end(), pMarker->maStrokes.begin(), - pMarker->maStrokes.end()); - rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; - rCustomAnnotationMarker.maFillColor = pMarker->maFillColor; + + aInfo.maPolygons = pMarker->maStrokes; + + aInfo.mnWidth = pMarker->mnWidth; + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.mbColor = true; + aInfo.maFillColor = pMarker->maFillColor; + aInfo.mbFillColor = true; } else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Highlight) { - if (!rCustomAnnotationMarker.maLineColor.IsTransparent()) - rCustomAnnotationMarker.maLineColor.SetAlpha(255 - 0x90); + aInfo.meType = sdr::annotation::AnnotationType::Highlight; + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerHighlight*>( rPDFAnnotation.mpMarker.get()); - rCustomAnnotationMarker.maPolygons.insert( - rCustomAnnotationMarker.maPolygons.end(), pMarker->maQuads.begin(), - pMarker->maQuads.end()); - rCustomAnnotationMarker.mnLineWidth = 1; - rCustomAnnotationMarker.maFillColor = rPDFAnnotation.maColor; - if (!rCustomAnnotationMarker.maFillColor.IsTransparent()) - rCustomAnnotationMarker.maFillColor.SetAlpha(255 - 0x90); + + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.maColor.SetAlpha(0xFF - 0x90); + aInfo.mbColor = true; + + aInfo.mnWidth = 1; + + aInfo.maFillColor = rPDFAnnotation.maColor; + aInfo.maFillColor.SetAlpha(0xFF - 0x90); + aInfo.mbFillColor = true; + + aInfo.maPolygons = pMarker->maQuads; } else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Line) { auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerLine*>( rPDFAnnotation.mpMarker.get()); - basegfx::B2DPolygon aPoly; - aPoly.append(pMarker->maLineStart); - aPoly.append(pMarker->maLineEnd); - rCustomAnnotationMarker.maPolygons.push_back(aPoly); + aInfo.meType = sdr::annotation::AnnotationType::Line; + + basegfx::B2DPolygon aPolygon; + aPolygon.append(pMarker->maLineStart); + aPolygon.append(pMarker->maLineEnd); + aInfo.maPolygons.push_back(aPolygon); - rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; - rCustomAnnotationMarker.maFillColor = COL_TRANSPARENT; + aInfo.mnWidth = pMarker->mnWidth; + aInfo.maColor = rPDFAnnotation.maColor; + aInfo.mbColor = true; + aInfo.mbFillColor = false; } + else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::FreeText) + { + aInfo.meType = sdr::annotation::AnnotationType::FreeText; + } + + xAnnotation->setCreationInfo(aInfo); } - else if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::FreeText) - { - xAnnotation->setIsFreeText(true); - } + + pPage->addAnnotation(xAnnotation, -1); } } mrDocument.setLock(bWasLocked); diff --git a/sd/source/ui/annotations/annotationmanager.cxx b/sd/source/ui/annotations/annotationmanager.cxx index 1446756d339a..ee5662fd2bcf 100644 --- a/sd/source/ui/annotations/annotationmanager.cxx +++ b/sd/source/ui/annotations/annotationmanager.cxx @@ -29,6 +29,7 @@ #include <vcl/settings.hxx> #include <vcl/svapp.hxx> #include <vcl/weld.hxx> +#include <tools/gen.hxx> #include <sal/macros.h> #include <svl/itempool.hxx> @@ -70,9 +71,24 @@ #include <sdpage.hxx> #include <drawdoc.hxx> #include <svx/annotation/TextAPI.hxx> +#include <svx/annotation/AnnotationObject.hxx> +#include <svx/annotation/ObjectAnnotationData.hxx> #include <optsitem.hxx> #include <sdmod.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdotext.hxx> + +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnwtit.hxx> + #include <memory> using namespace ::com::sun::star; @@ -202,7 +218,6 @@ void AnnotationManagerImpl::disposing (std::unique_lock<std::mutex>&) } removeListener(); - DisposeTags(); if( mnUpdateTagsEvent ) { @@ -328,8 +343,6 @@ void AnnotationManagerImpl::ExecuteInsertAnnotation(SfxRequest const & rReq) void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest const & rReq) { - ShowAnnotations( true ); - const SfxItemSet* pArgs = rReq.GetArgs(); switch( rReq.GetSlot() ) @@ -440,50 +453,48 @@ void AnnotationManagerImpl::ExecuteEditAnnotation(SfxRequest const & rReq) void AnnotationManagerImpl::InsertAnnotation(const OUString& rText) { SdPage* pPage = GetCurrentPage(); - if( !pPage ) + if (!pPage) return; - if( mpDoc->IsUndoEnabled() ) - mpDoc->BegUndo( SdResId( STR_ANNOTATION_UNDO_INSERT ) ); + if (mpDoc->IsUndoEnabled()) + mpDoc->BegUndo(SdResId(STR_ANNOTATION_UNDO_INSERT)); // find free space for new annotation - int y = 0, x = 0; + int y = 0; + int x = 0; sdr::annotation::AnnotationVector aAnnotations(pPage->getAnnotations()); - if( !aAnnotations.empty() ) + if (!aAnnotations.empty()) { - const int page_width = pPage->GetSize().Width(); - const int width = 1000; - const int height = 800; - ::tools::Rectangle aTagRect; + const int fPageWidth = pPage->GetSize().Width(); + const int fWidth = 1000; + const int fHeight = 800; - while( true ) + while (true) { - ::tools::Rectangle aNewRect( x, y, x + width - 1, y + height - 1 ); + ::tools::Rectangle aNewRect(Point(x, y), Size(fWidth, fHeight)); bool bFree = true; - for( const auto& rxAnnotation : aAnnotations ) + for (const auto& rxAnnotation : aAnnotations) { - RealPoint2D aPoint( rxAnnotation->getPosition() ); - aTagRect.SetLeft( sal::static_int_cast< ::tools::Long >( aPoint.X * 100.0 ) ); - aTagRect.SetTop( sal::static_int_cast< ::tools::Long >( aPoint.Y * 100.0 ) ); - aTagRect.SetRight( aTagRect.Left() + width - 1 ); - aTagRect.SetBottom( aTagRect.Top() + height - 1 ); + RealPoint2D aRealPoint2D(rxAnnotation->getPosition()); + Point aPoint(::tools::Long(aRealPoint2D.X * 100.0), ::tools::Long(aRealPoint2D.Y * 100.0)); + Size aSize(fWidth, fHeight); - if( aNewRect.Overlaps( aTagRect ) ) + if (aNewRect.Overlaps(::tools::Rectangle(aPoint, aSize))) { bFree = false; break; } } - if( !bFree ) + if (!bFree) { - x += width; - if( x > page_width ) + x += fWidth; + if (x > fPageWidth) { x = 0; - y += height; + y += fHeight; } } else @@ -517,17 +528,20 @@ void AnnotationManagerImpl::InsertAnnotation(const OUString& rText) xAnnotation->setDateTime( getCurrentDateTime() ); // set position - RealPoint2D aPos( static_cast<double>(x) / 100.0, static_cast<double>(y) / 100.0 ); - xAnnotation->setPosition( aPos ); + RealPoint2D aPosition(x / 100.0, y / 100.0); + xAnnotation->setPosition(aPosition); + xAnnotation->setSize({5.0, 5.0}); - if( mpDoc->IsUndoEnabled() ) + pPage->addAnnotation(xAnnotation, -1); + + if (mpDoc->IsUndoEnabled()) mpDoc->EndUndo(); // Tell our LOK clients about new comment added LOKCommentNotifyAll(sdr::annotation::CommentNotificationType::Add, *xAnnotation); UpdateTags(true); - SelectAnnotation( xAnnotation, true ); + SelectAnnotation(xAnnotation, true); } void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest const & rReq ) @@ -648,8 +662,6 @@ void AnnotationManagerImpl::DeleteAnnotation(rtl::Reference<sdr::annotation::Ann if( mpDoc->IsUndoEnabled() ) mpDoc->EndUndo(); - - UpdateTags(); } } @@ -693,8 +705,8 @@ void AnnotationManagerImpl::DeleteAllAnnotations() if( pPage && !pPage->getAnnotations().empty() ) { - - for( const auto& rxAnnotation : pPage->getAnnotations()) + std::vector<rtl::Reference<sdr::annotation::Annotation>> aAnnotations(pPage->getAnnotations()); // intentionally copy + for( const auto& rxAnnotation : aAnnotations) { pPage->removeAnnotation( rxAnnotation ); } @@ -857,33 +869,9 @@ void AnnotationManagerImpl::SelectNextAnnotation(bool bForward) while( true ); } -void AnnotationManagerImpl::onTagSelected( AnnotationTag const & rTag ) -{ - mxSelectedAnnotation = rTag.GetAnnotation(); - invalidateSlots(); -} - -void AnnotationManagerImpl::onTagDeselected( AnnotationTag const & rTag ) -{ - if (rTag.GetAnnotation() == mxSelectedAnnotation) - { - mxSelectedAnnotation.clear(); - invalidateSlots(); - } -} - -void AnnotationManagerImpl::SelectAnnotation(rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, bool bEdit) +void AnnotationManagerImpl::SelectAnnotation(rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, bool /*bEdit*/) { mxSelectedAnnotation = xAnnotation; - - auto iter = std::find_if(maTagVector.begin(), maTagVector.end(), - [&xAnnotation](const rtl::Reference<AnnotationTag>& rxTag) { return rxTag->GetAnnotation() == xAnnotation; }); - if (iter != maTagVector.end()) - { - SmartTagReference xTag( *iter ); - mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag ); - (*iter)->OpenPopup( bEdit ); - } } void AnnotationManagerImpl::GetSelectedAnnotation( rtl::Reference<sdr::annotation::Annotation>& xAnnotation ) @@ -908,109 +896,197 @@ void AnnotationManagerImpl::invalidateSlots() void AnnotationManagerImpl::onSelectionChanged() { - if( !(mxView.is() && mrBase.GetDrawView()) ) + if (!mxView.is() || !mrBase.GetDrawView()) return; - try + rtl::Reference<SdPage> xPage = mrBase.GetMainViewShell()->getCurrentPage(); + if (xPage != mxCurrentPage) { - rtl::Reference< SdPage > xPage = mrBase.GetMainViewShell()->getCurrentPage(); - - if( xPage != mxCurrentPage ) - { - mxCurrentPage = xPage; - - UpdateTags(true); - } - } - catch( Exception& ) - { - TOOLS_WARN_EXCEPTION( "sd", "sd::AnnotationManagerImpl::onSelectionChanged()" ); + mxCurrentPage = xPage; + UpdateTags(true); } } -void AnnotationManagerImpl::UpdateTags( bool bSynchron ) +void AnnotationManagerImpl::UpdateTags(bool bSynchron) { - if( bSynchron ) + SyncAnnotationObjects(); + + invalidateSlots(); + + if (bSynchron) { - if( mnUpdateTagsEvent ) - Application::RemoveUserEvent( mnUpdateTagsEvent ); + if (mnUpdateTagsEvent) + Application::RemoveUserEvent(mnUpdateTagsEvent); UpdateTagsHdl(nullptr); } else { - if( !mnUpdateTagsEvent && mxView.is() ) - mnUpdateTagsEvent = Application::PostUserEvent( LINK( this, AnnotationManagerImpl, UpdateTagsHdl ) ); + if (!mnUpdateTagsEvent && mxView.is()) + mnUpdateTagsEvent = Application::PostUserEvent(LINK(this, AnnotationManagerImpl, UpdateTagsHdl)); } } IMPL_LINK_NOARG(AnnotationManagerImpl, UpdateTagsHdl, void*, void) { mnUpdateTagsEvent = nullptr; - DisposeTags(); - - if( mbShowAnnotations ) - CreateTags(); + SyncAnnotationObjects(); - if( mrBase.GetDrawView() ) - static_cast< ::sd::View* >( mrBase.GetDrawView() )->updateHandles(); + if (mrBase.GetDrawView()) + static_cast<::sd::View*>(mrBase.GetDrawView())->updateHandles(); invalidateSlots(); } -void AnnotationManagerImpl::CreateTags() +SdrObject* AnnotationManagerImpl::findAnnotationObjectMatching(rtl::Reference<sdr::annotation::Annotation> const& xAnnotation) +{ + for (size_t i = 0; i < mxCurrentPage->GetObjCount(); ++i) + { + SdrObject* pObject = mxCurrentPage->GetObj(i); + if (pObject->isAnnotationObject() && pObject->getAnnotationData()->mxAnnotation == xAnnotation) + return pObject; + } + return nullptr; +} + +namespace +{ + +void applyAnnotationCommon(SdrObject& rObject, rtl::Reference<sdr::annotation::Annotation> const& xAnnotation) +{ + rObject.setAsAnnotationObject(true); + auto& xAnnotationData = rObject.getAnnotationData(); + xAnnotationData->mxAnnotation = xAnnotation; + rObject.SetPrintable(false); +} + +void applyAnnotationProperties(SdrObject& rObject, sdr::annotation::CreationInfo const& rInfo) +{ + if (rInfo.mbColor) + { + rObject.SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID)); + rObject.SetMergedItem(XLineColorItem(OUString(), rInfo.maColor)); + } + rObject.SetMergedItem(XLineWidthItem(rInfo.mnWidth)); + + if (rInfo.mbFillColor) + { + rObject.SetMergedItem(XFillStyleItem(drawing::FillStyle_SOLID)); + rObject.SetMergedItem(XFillColorItem(OUString(), rInfo.maFillColor)); + } +} + +} + +void AnnotationManagerImpl::SyncAnnotationObjects() { - if( !(mxCurrentPage.is() && mpDoc) ) + if (!mxCurrentPage.is() || !mpDoc) return; auto xViewShell = mrBase.GetMainViewShell(); if (!xViewShell) return; - try + sal_Int32 nIndex = 1; + for (auto const& xAnnotation : mxCurrentPage->getAnnotations()) { - int nIndex = 1; - maFont = Application::GetSettings().GetStyleSettings().GetAppFont(); + SdrObject* pObject = findAnnotationObjectMatching(xAnnotation); + + if (pObject) + continue; + + auto const& rInfo = xAnnotation->getCreationInfo(); + + auto* pView = xViewShell->GetView(); + auto& rModel = pView->getSdrModelFromSdrView(); - rtl::Reference< AnnotationTag > xSelectedTag; + auto aRealPoint2D = xAnnotation->getPosition(); + Point aPosition(::tools::Long(aRealPoint2D.X * 100.0), ::tools::Long(aRealPoint2D.Y * 100.0)); - for (rtl::Reference<sdr::annotation::Annotation> const& xAnnotation : mxCurrentPage->getAnnotations()) + auto aRealSize2D = xAnnotation->getSize(); + Size aSize(::tools::Long(aRealSize2D.Width * 100.0), ::tools::Long(aRealSize2D.Height * 100.0)); + + ::tools::Rectangle aRectangle(aPosition, aSize); + + rtl::Reference<SdrObject> pNewObject; + + if (rInfo.meType == sdr::annotation::AnnotationType::None) { - Color aColor( GetColorLight( mpDoc->GetAnnotationAuthorIndex( xAnnotation->getAuthor() ) ) ); - rtl::Reference< AnnotationTag > xTag( new AnnotationTag( *this, *xViewShell->GetView(), xAnnotation, aColor, nIndex++, maFont ) ); - maTagVector.push_back(xTag); + sal_uInt16 nAuthorIndex = mpDoc->GetAnnotationAuthorIndex(xAnnotation->getAuthor()); - if (xAnnotation == mxSelectedAnnotation) + sdr::annotation::AnnotationViewData aAnnotationViewData { - xSelectedTag = xTag; - } + .nIndex = nIndex, + .nAuthorIndex = nAuthorIndex + }; + + rtl::Reference<sdr::annotation::AnnotationObject> pAnnotationObject = new sdr::annotation::AnnotationObject(rModel, aRectangle, aAnnotationViewData); + pNewObject = pAnnotationObject; + + applyAnnotationCommon(*pNewObject, xAnnotation); + + pAnnotationObject->ApplyAnnotationName(); + } + else if (rInfo.meType == sdr::annotation::AnnotationType::FreeText) + { + rtl::Reference<SdrRectObj> pRectangleObject = new SdrRectObj(rModel, SdrObjKind::Text, aRectangle); + pNewObject = pRectangleObject; + + applyAnnotationCommon(*pNewObject, xAnnotation); + applyAnnotationProperties(*pNewObject, rInfo); + + OUString aString = xAnnotation->getTextRange()->getString(); + pRectangleObject->SetText(aString); } + else if (rInfo.meType == sdr::annotation::AnnotationType::Square) + { + pNewObject = new SdrRectObj(rModel, SdrObjKind::Rectangle, aRectangle); - if( xSelectedTag.is() ) + applyAnnotationCommon(*pNewObject, xAnnotation); + applyAnnotationProperties(*pNewObject, rInfo); + } + else if (rInfo.meType == sdr::annotation::AnnotationType::Circle) { - SmartTagReference xTag( xSelectedTag ); - mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag ); + pNewObject = new SdrCircObj(rModel, SdrCircKind::Full, aRectangle); + + applyAnnotationCommon(*pNewObject, xAnnotation); + applyAnnotationProperties(*pNewObject, rInfo); } else { - // no tag, no selection! - mxSelectedAnnotation.clear(); + SdrObjKind ekind = SdrObjKind::Polygon; + + switch (rInfo.meType) + { + case sdr::annotation::AnnotationType::Polygon: + ekind = SdrObjKind::Polygon; + break; + case sdr::annotation::AnnotationType::Line: + ekind = SdrObjKind::PolyLine; + break; + case sdr::annotation::AnnotationType::Ink: + ekind = SdrObjKind::FreehandLine; + break; + default: + break; + } + + basegfx::B2DPolyPolygon aPolyPolygon; + for (auto const& rPolygon : rInfo.maPolygons) + aPolyPolygon.append(rPolygon); + + pNewObject = new SdrPathObj(rModel, ekind, aPolyPolygon); + + applyAnnotationCommon(*pNewObject, xAnnotation); + applyAnnotationProperties(*pNewObject, rInfo); } - } - catch( Exception& ) - { - TOOLS_WARN_EXCEPTION( "sd", "sd::AnnotationManagerImpl::onSelectionChanged()" ); - } -} -void AnnotationManagerImpl::DisposeTags() -{ - for (auto& rxTag : maTagVector) - { - rxTag->Dispose(); - } + pNewObject->SetLogicRect(aRectangle); - maTagVector.clear(); + pView->InsertObjectAtView(pNewObject.get(), *pView->GetSdrPageView()); + + nIndex++; + } } void AnnotationManagerImpl::addListener() @@ -1049,60 +1125,6 @@ IMPL_LINK(AnnotationManagerImpl,EventMultiplexerListener, } } -void AnnotationManagerImpl::ExecuteAnnotationTagContextMenu(const rtl::Reference<sdr::annotation::Annotation>& xAnnotation, weld::Widget* pParent, const ::tools::Rectangle& rContextRect) -{ - SfxDispatcher* pDispatcher( getDispatcher( mrBase ) ); - if( !pDispatcher ) - return; - - const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly(); - - if (bReadOnly) - return; - - std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/annotationtagmenu.ui"_ustr)); - std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu"_ustr)); - - SvtUserOptions aUserOptions; - OUString sCurrentAuthor( aUserOptions.GetFullName() ); - OUString sAuthor( xAnnotation->getAuthor() ); - - OUString aStr(xMenu->get_label(u".uno:DeleteAllAnnotationByAuthor"_ustr)); - OUString aReplace( sAuthor ); - if( aReplace.isEmpty() ) - aReplace = SdResId( STR_ANNOTATION_NOAUTHOR ); - aStr = aStr.replaceFirst("%1", aReplace); - xMenu->set_label(u".uno:DeleteAllAnnotationByAuthor"_ustr, aStr); - - bool bShowReply = sAuthor != sCurrentAuthor; - xMenu->set_visible(u".uno:ReplyToAnnotation"_ustr, bShowReply); - xMenu->set_visible(u"separator"_ustr, bShowReply); - xMenu->set_visible(u".uno:DeleteAnnotation"_ustr, xAnnotation.is()); - - auto sId = xMenu->popup_at_rect(pParent, rContextRect); - - if (sId == ".uno:ReplyToAnnotation") - { - const SfxUnoAnyItem aItem( SID_REPLYTO_POSTIT, Any( css::uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(xAnnotation.get())) ) ); - pDispatcher->ExecuteList(SID_REPLYTO_POSTIT, - SfxCallMode::ASYNCHRON, { &aItem }); - } - else if (sId == ".uno:DeleteAnnotation") - { - const SfxUnoAnyItem aItem( SID_REPLYTO_POSTIT, Any( css::uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(xAnnotation.get())) ) ); - pDispatcher->ExecuteList(SID_DELETE_POSTIT, SfxCallMode::ASYNCHRON, - { &aItem }); - } - else if (sId == ".uno:DeleteAllAnnotationByAuthor") - { - const SfxStringItem aItem( SID_DELETEALLBYAUTHOR_POSTIT, sAuthor ); - pDispatcher->ExecuteList( SID_DELETEALLBYAUTHOR_POSTIT, - SfxCallMode::ASYNCHRON, { &aItem }); - } - else if (sId == ".uno:DeleteAllAnnotation") - pDispatcher->Execute( SID_DELETEALL_POSTIT ); -} - Color AnnotationManagerImpl::GetColor(sal_uInt16 aAuthorIndex) { if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode()) diff --git a/sd/source/ui/annotations/annotationmanagerimpl.hxx b/sd/source/ui/annotations/annotationmanagerimpl.hxx index 1a7b60263089..a92883dec583 100644 --- a/sd/source/ui/annotations/annotationmanagerimpl.hxx +++ b/sd/source/ui/annotations/annotationmanagerimpl.hxx @@ -25,13 +25,12 @@ #include <comphelper/compbase.hxx> -#include "annotationtag.hxx" - namespace com::sun::star::drawing { class XDrawView; } namespace com::sun::star::office { class XAnnotationAccess; } namespace com::sun::star::office { class XAnnotation; } class SfxRequest; +class SdrObject; class SdPage; class SdDrawDocument; struct ImplSVEvent; @@ -42,6 +41,7 @@ namespace sd { class Annotation; class ViewShellBase; +class View; namespace tools { class EventMultiplexerEvent; } @@ -87,10 +87,6 @@ public: static Color GetColorLight(sal_uInt16 aAuthorIndex); static Color GetColor(sal_uInt16 aAuthorIndex); - // callbacks - void onTagSelected( AnnotationTag const & rTag ); - void onTagDeselected( AnnotationTag const & rTag ); - void onSelectionChanged(); void addListener(); @@ -102,8 +98,7 @@ public: DECL_LINK(UpdateTagsHdl, void *, void); void UpdateTags(bool bSynchron = false); - void CreateTags(); - void DisposeTags(); + void SyncAnnotationObjects(); SdPage* GetNextPage( SdPage const * pPage, bool bForward ); @@ -113,19 +108,18 @@ public: void ShowAnnotations(bool bShow); + SdrObject* findAnnotationObjectMatching(rtl::Reference<sdr::annotation::Annotation> const& xAnnotation); + private: ViewShellBase& mrBase; SdDrawDocument* mpDoc; - std::vector< rtl::Reference< AnnotationTag > > maTagVector; - css::uno::Reference< css::drawing::XDrawView > mxView; rtl::Reference<SdPage> mxCurrentPage; rtl::Reference<sdr::annotation::Annotation> mxSelectedAnnotation; bool mbShowAnnotations; ImplSVEvent * mnUpdateTagsEvent; - vcl::Font maFont; rtl::Reference<sdr::annotation::Annotation> GetAnnotationById(sal_uInt32 nAnnotationId); }; diff --git a/sd/source/ui/annotations/annotationtag.cxx b/sd/source/ui/annotations/annotationtag.cxx deleted file mode 100644 index 91cfcbbfbcfa..000000000000 --- a/sd/source/ui/annotations/annotationtag.cxx +++ /dev/null @@ -1,669 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <com/sun/star/geometry/RealPoint2D.hpp> -#include <com/sun/star/office/XAnnotation.hpp> - -#include <rtl/ustrbuf.hxx> - -#include <utility> -#include <vcl/commandevent.hxx> -#include <vcl/svapp.hxx> -#include <vcl/settings.hxx> -#include <vcl/weldutils.hxx> - -#include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> -#include <svx/sdr/overlay/overlaybitmapex.hxx> -#include <svx/sdr/overlay/overlaypolypolygon.hxx> -#include <svx/svdpagv.hxx> -#include <svx/sdrpagewindow.hxx> -#include <svx/sdrpaintwindow.hxx> -#include <svx/svddrgmt.hxx> -#include <tools/debug.hxx> - -#include <View.hxx> -#include <sdresid.hxx> -#include <strings.hrc> -#include "annotationmanagerimpl.hxx" -#include "annotationwindow.hxx" -#include "annotationtag.hxx" -#include <svx/annotation/Annotation.hxx> -#include <Annotation.hxx> -#include <ViewShell.hxx> -#include <Window.hxx> -#include <drawdoc.hxx> - -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::geometry; - -namespace sd -{ - -const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32; -const int DRGPIX = 2; // Drag MinMove in Pixel - -static OUString getInitials( const OUString& rName ) -{ - OUStringBuffer sInitials; - - const sal_Unicode * pStr = rName.getStr(); - sal_Int32 nLength = rName.getLength(); - - while( nLength ) - { - // skip whitespace - while( nLength && (*pStr <= ' ') ) - { - nLength--; pStr++; - } - - // take letter - if( nLength ) - { - sInitials.append(*pStr); - nLength--; pStr++; - } - - // skip letters until whitespace - while( nLength && (*pStr > ' ') ) - { - nLength--; pStr++; - } - } - - return sInitials.makeStringAndClear(); -} - -namespace { - -class AnnotationDragMove : public SdrDragMove -{ -public: - AnnotationDragMove(SdrDragView& rNewView, rtl::Reference <AnnotationTag > xTag); - virtual bool BeginSdrDrag() override; - virtual bool EndSdrDrag(bool bCopy) override; - virtual void MoveSdrDrag(const Point& rNoSnapPnt) override; - virtual void CancelSdrDrag() override; - -private: - rtl::Reference <AnnotationTag > mxTag; - Point maOrigin; -}; - -} - -AnnotationDragMove::AnnotationDragMove(SdrDragView& rNewView, rtl::Reference <AnnotationTag > xTag) -: SdrDragMove(rNewView) -, mxTag(std::move( xTag )) -{ -} - -bool AnnotationDragMove::BeginSdrDrag() -{ - DragStat().SetRef1(GetDragHdl()->GetPos()); - DragStat().SetShown(!DragStat().IsShown()); - - maOrigin = GetDragHdl()->GetPos(); - DragStat().SetActionRect(::tools::Rectangle(maOrigin,maOrigin)); - - return true; -} - -void AnnotationDragMove::MoveSdrDrag(const Point& rNoSnapPnt) -{ - Point aPnt(rNoSnapPnt); - - if (DragStat().CheckMinMoved(rNoSnapPnt)) - { - if (aPnt!=DragStat().GetNow()) - { - Hide(); - DragStat().NextMove(aPnt); - GetDragHdl()->SetPos( maOrigin + Point( DragStat().GetDX(), DragStat().GetDY() ) ); - Show(); - DragStat().SetActionRect(::tools::Rectangle(aPnt,aPnt)); - } - } -} - -bool AnnotationDragMove::EndSdrDrag(bool /*bCopy*/) -{ - Hide(); - if( mxTag.is() ) - mxTag->Move( DragStat().GetDX(), DragStat().GetDY() ); - return true; -} - -void AnnotationDragMove::CancelSdrDrag() -{ - Hide(); -} - -namespace { - -class AnnotationHdl : public SmartHdl -{ -public: - AnnotationHdl( const SmartTagReference& xTag, rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, const Point& rPnt ); - - virtual void CreateB2dIAObject() override; - virtual bool IsFocusHdl() const override; - -private: - rtl::Reference<sdr::annotation::Annotation> mxAnnotation; - rtl::Reference<AnnotationTag> mxTag; -}; - -} - -AnnotationHdl::AnnotationHdl( const SmartTagReference& xTag, rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, const Point& rPnt ) - : SmartHdl(xTag, rPnt, SdrHdlKind::SmartTag) - , mxAnnotation(xAnnotation) - , mxTag(dynamic_cast<AnnotationTag*>(xTag.get())) -{ -} - -void AnnotationHdl::CreateB2dIAObject() -{ - // first throw away old one - GetRidOfIAObject(); - - if (!mxAnnotation.is()) - return; - - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - - const Point aTagPos( GetPos() ); - basegfx::B2DPoint aPosition( aTagPos.X(), aTagPos.Y() ); - - const bool bFocused = IsFocusHdl() && m_pHdlList && (m_pHdlList->GetFocusHdl() == this); - - BitmapEx aBitmapEx( mxTag->CreateAnnotationBitmap(mxTag->isSelected()) ); - BitmapEx aBitmapEx2; - if( bFocused ) - aBitmapEx2 = mxTag->CreateAnnotationBitmap(!mxTag->isSelected() ); - - if(!m_pHdlList) - return; - - SdrMarkView* pView = m_pHdlList->GetView(); - - if(!pView || pView->areMarkHandlesHidden()) - return; - - SdrPageView* pPageView = pView->GetSdrPageView(); - - if(!pPageView) - return; - - for(sal_uInt32 b = 0; b < pPageView->PageWindowCount(); b++) - { - // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; - const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); - - SdrPaintWindow& rPaintWindow = rPageWindow.GetPaintWindow(); - const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); - if(rPaintWindow.OutputToWindow() && xManager.is() ) - { - std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject; - auto pSdAnnotation = dynamic_cast<sd::Annotation*>(mxAnnotation.get()); - if (pSdAnnotation && pSdAnnotation->hasCustomAnnotationMarker()) - { - CustomAnnotationMarker& rCustomAnnotationMarker = pSdAnnotation->getCustomAnnotationMarker(); - - auto& rPolygons = rCustomAnnotationMarker.maPolygons; - if (!rPolygons.empty()) - { - basegfx::B2DPolyPolygon aPolyPolygon; - for (auto const & rPolygon : rPolygons) - aPolyPolygon.append(rPolygon); - - pOverlayObject.reset(new sdr::overlay::OverlayPolyPolygon( - std::move(aPolyPolygon), - rCustomAnnotationMarker.maLineColor, - rCustomAnnotationMarker.mnLineWidth, - rCustomAnnotationMarker.maFillColor)); - } - } - else - { - // animate focused handles - if(bFocused) - { - const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime(); - - pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBitmapEx, aBitmapEx2, nBlinkTime, 0, 0, 0, 0 )); - } - else - { - pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 )); - } - } - - // OVERLAYMANAGER - insertNewlyCreatedOverlayObjectForSdrHdl( - std::move(pOverlayObject), - rPageWindow.GetObjectContact(), - *xManager); - } - } -} - -bool AnnotationHdl::IsFocusHdl() const -{ - return true; -} - -AnnotationTag::AnnotationTag(AnnotationManagerImpl& rManager, ::sd::View& rView, rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, Color const & rColor, int nIndex, const vcl::Font& rFont) -: SmartTag( rView ) -, mrManager( rManager ) -, mxAnnotation( xAnnotation ) -, maColor( rColor ) -, mnIndex( nIndex ) -, mrFont( rFont ) -, mpListenWindow( nullptr ) -{ -} - -AnnotationTag::~AnnotationTag() -{ - DBG_ASSERT( !mxAnnotation.is(), "sd::AnnotationTag::~AnnotationTag(), dispose me first!" ); - Dispose(); -} - -/** returns true if the AnnotationTag handled the event. */ -bool AnnotationTag::MouseButtonDown( const MouseEvent& rMEvt, SmartHdl& /*rHdl*/ ) -{ - if( !mxAnnotation.is() ) - return false; - - bool bRet = false; - if( !isSelected() ) - { - SmartTagReference xTag( this ); - mrView.getSmartTags().select( xTag ); - bRet = true; - } - - if( rMEvt.IsLeft() && !rMEvt.IsRight() ) - { - vcl::Window* pWindow = mrView.GetViewShell()->GetActiveWindow(); - if( pWindow ) - { - maMouseDownPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() ); - - if( mpListenWindow ) - mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler)); - - mpListenWindow = pWindow; - mpListenWindow->AddEventListener( LINK(this, AnnotationTag, WindowEventHandler)); - } - - bRet = true; - } - - return bRet; -} - -/** returns true if the SmartTag consumes this event. */ -bool AnnotationTag::KeyInput( const KeyEvent& rKEvt ) -{ - if( !mxAnnotation.is() ) - return false; - - sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); - switch( nCode ) - { - case KEY_DELETE: - mrManager.DeleteAnnotation( mxAnnotation ); - return true; - - case KEY_DOWN: - case KEY_UP: - case KEY_LEFT: - case KEY_RIGHT: - return OnMove( rKEvt ); - - case KEY_ESCAPE: - { - SmartTagReference xThis( this ); - mrView.getSmartTags().deselect(); - return true; - } - - case KEY_TAB: - mrManager.SelectNextAnnotation(!rKEvt.GetKeyCode().IsShift()); - return true; - - case KEY_RETURN: - case KEY_SPACE: - OpenPopup( true ); - return true; - - default: - return false; - } -} - -/** returns true if the SmartTag consumes this event. */ -bool AnnotationTag::Command( const CommandEvent& rCEvt ) -{ - if (rCEvt.GetCommand() != CommandEventId::ContextMenu) - return false; - if (vcl::Window* pWindow = mrView.GetViewShell()->GetActiveWindow()) - { - ::tools::Rectangle aContextRect(rCEvt.GetMousePosPixel(),Size(1,1)); - weld::Window* pParent = weld::GetPopupParent(*pWindow, aContextRect); - mrManager.ExecuteAnnotationTagContextMenu(mxAnnotation, pParent, aContextRect); - return true; - } - return false; -} - -void AnnotationTag::Move( int nDX, int nDY ) -{ - if( !mxAnnotation.is() ) - return; - - if( mrManager.GetDoc()->IsUndoEnabled() ) - mrManager.GetDoc()->BegUndo( SdResId( STR_ANNOTATION_UNDO_MOVE ) ); - - RealPoint2D aPosition( mxAnnotation->getPosition() ); - aPosition.X += static_cast<double>(nDX) / 100.0; - aPosition.Y += static_cast<double>(nDY) / 100.0; - mxAnnotation->setPosition( aPosition ); - - if( mrManager.GetDoc()->IsUndoEnabled() ) - mrManager.GetDoc()->EndUndo(); - - mrView.updateHandles(); -} - -bool AnnotationTag::OnMove( const KeyEvent& rKEvt ) -{ - ::tools::Long nX = 0; - ::tools::Long nY = 0; - - switch( rKEvt.GetKeyCode().GetCode() ) - { - case KEY_UP: nY = -1; break; - case KEY_DOWN: nY = 1; break; - case KEY_LEFT: nX = -1; break; - case KEY_RIGHT: nX = 1; break; - default: break; - } - - if(rKEvt.GetKeyCode().IsMod2()) - { - OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow()->GetOutDev(); - Size aLogicSizeOnePixel = pOut ? pOut->PixelToLogic(Size(1,1)) : Size(100, 100); - nX *= aLogicSizeOnePixel.Width(); - nY *= aLogicSizeOnePixel.Height(); - } - else - { - // old, fixed move distance - nX *= 100; - nY *= 100; - } - - if( nX || nY ) - { - // move the annotation - Move( nX, nY ); - } - - return true; -} - -void AnnotationTag::CheckPossibilities() -{ -} - -sal_Int32 AnnotationTag::GetMarkablePointCount() const -{ - return 0; -} - -sal_Int32 AnnotationTag::GetMarkedPointCount() const -{ - return 0; -} - -bool AnnotationTag::MarkPoint(SdrHdl& /*rHdl*/, bool /*bUnmark*/ ) -{ - return false; -} - -bool AnnotationTag::MarkPoints(const ::tools::Rectangle* /*pRect*/, bool /*bUnmark*/ ) -{ - return false; -} - -bool AnnotationTag::getContext( SdrViewContext& /*rContext*/ ) -{ - return false; -} - -void AnnotationTag::addCustomHandles( SdrHdlList& rHandlerList ) -{ - if( !mxAnnotation.is() ) - return; - - SmartTagReference xThis( this ); - std::unique_ptr<AnnotationHdl> pHdl(new AnnotationHdl( xThis, mxAnnotation, Point() )); - pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM ); - pHdl->SetPageView( mrView.GetSdrPageView() ); - - RealPoint2D aPosition( mxAnnotation->getPosition() ); - Point aBasePos( static_cast<::tools::Long>(aPosition.X * 100.0), static_cast<::tools::Long>(aPosition.Y * 100.0) ); - pHdl->SetPos( aBasePos ); - - rHandlerList.AddHdl( std::move(pHdl) ); -} - -void AnnotationTag::disposing() -{ - if( mpListenWindow ) - { - mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler)); - } - - mxAnnotation.clear(); - ClosePopup(); - SmartTag::disposing(); -} - -void AnnotationTag::select() -{ - SmartTag::select(); - - mrManager.onTagSelected( *this ); - - vcl::Window* pWindow = mrView.GetViewShell()->GetActiveWindow(); - if( pWindow ) - { - RealPoint2D aPosition( mxAnnotation->getPosition() ); - Point aPos( static_cast<::tools::Long>(aPosition.X * 100.0), static_cast<::tools::Long>(aPosition.Y * 100.0) ); - - ::tools::Rectangle aVisRect( aPos, pWindow->PixelToLogic(maSize) ); - mrView.MakeVisible(aVisRect, *pWindow); - } -} - -void AnnotationTag::deselect() -{ - SmartTag::deselect(); - - ClosePopup(); - - mrManager.onTagDeselected( *this ); -} - -BitmapEx AnnotationTag::CreateAnnotationBitmap( bool bSelected ) -{ - ScopedVclPtrInstance< VirtualDevice > pVDev; - - OUString sText; - if (mxAnnotation && mxAnnotation->isFreeText()) - { - sText = mxAnnotation->getTextRange()->getString(); - } - else - { - OUString sInitials(mxAnnotation->getInitials()); - if (sInitials.isEmpty()) - { - sInitials = getInitials(mxAnnotation->getAuthor()); - } - - sText = sInitials + " " + OUString::number(mnIndex); - } - - pVDev->SetFont( mrFont ); - - const int BORDER_X = 4; // pixels - const int BORDER_Y = 4; // pixels - - maSize = Size(pVDev->GetTextWidth(sText) + 2 * BORDER_X, pVDev->GetTextHeight() + 2 * BORDER_Y); - pVDev->SetOutputSizePixel( maSize, false ); - - Color aBorderColor( maColor ); - - if( bSelected ) - { - aBorderColor.Invert(); - } - else - { - if( maColor.IsDark() ) - { - aBorderColor.IncreaseLuminance( 32 ); - } - else - { - aBorderColor.DecreaseLuminance( 32 ); - } - } - - Point aPos; - ::tools::Rectangle aBorderRect( aPos, maSize ); - pVDev->SetLineColor(aBorderColor); - pVDev->SetFillColor(maColor); - pVDev->DrawRect( aBorderRect ); - - pVDev->SetTextColor( maColor.IsDark() ? COL_WHITE : COL_BLACK ); - pVDev->DrawText(Point(BORDER_X, BORDER_Y), sText); - - return pVDev->GetBitmapEx( aPos, maSize ); -} - -void AnnotationTag::OpenPopup( bool bEdit ) -{ - if( !mxAnnotation.is() ) - return; - - if( !mpAnnotationWindow ) - { - OutputDevice* pOut = getView().GetFirstOutputDevice(); - vcl::Window* pWindow = pOut ? pOut->GetOwnerWindow() : nullptr; - if( pWindow ) - { - RealPoint2D aPosition( mxAnnotation->getPosition() ); - Point aPos(pWindow->LogicToPixel( Point( static_cast<::tools::Long>(aPosition.X * 100.0), static_cast<::tools::Long>(aPosition.Y * 100.0) ) ) ); - - aPos.AdjustX(4 ); // magic! - aPos.AdjustY(1 ); - - ::tools::Rectangle aRect( aPos, maSize ); - - weld::Window* pParent = weld::GetPopupParent(*pWindow, aRect); - mpAnnotationWindow.reset(new AnnotationWindow(pParent, aRect, mrView.GetDocSh(), mxAnnotation)); - mpAnnotationWindow->connect_closed(LINK(this, AnnotationTag, PopupModeEndHdl)); - } - } - - if (bEdit && mpAnnotationWindow) - mpAnnotationWindow->StartEdit(); -} - -IMPL_LINK_NOARG(AnnotationTag, PopupModeEndHdl, weld::Popover&, void) -{ - ClosePopup(); -} - -void AnnotationTag::ClosePopup() -{ - if (mpAnnotationWindow) - { - mpAnnotationWindow->SaveToDocument(); - mpAnnotationWindow.reset(); - } -} - -IMPL_LINK(AnnotationTag, WindowEventHandler, VclWindowEvent&, rEvent, void) -{ - vcl::Window* pWindow = rEvent.GetWindow(); - - if( !pWindow ) - return; - - if( pWindow != mpListenWindow ) - return; - - switch( rEvent.GetId() ) - { - case VclEventId::WindowMouseButtonUp: - { - // if we stop pressing the button without a mouse move we open the popup - mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler)); - mpListenWindow = nullptr; - if( !mpAnnotationWindow ) - OpenPopup(false); - } - break; - case VclEventId::WindowMouseMove: - { - // if we move the mouse after a button down we want to start dragging - mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler)); - mpListenWindow = nullptr; - - SdrHdl* pHdl = mrView.PickHandle(maMouseDownPos); - if( pHdl ) - { - mrView.BrkAction(); - const sal_uInt16 nDrgLog = static_cast<sal_uInt16>(pWindow->PixelToLogic(Size(DRGPIX,0)).Width()); - - rtl::Reference< AnnotationTag > xTag( this ); - - SdrDragMethod* pDragMethod = new AnnotationDragMove( mrView, xTag ); - mrView.BegDragObj(maMouseDownPos, nullptr, pHdl, nDrgLog, pDragMethod ); - } - } - break; - case VclEventId::ObjectDying: - mpListenWindow = nullptr; - break; - default: break; - } -} - -} // end of namespace sd - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/annotations/annotationtag.hxx b/sd/source/ui/annotations/annotationtag.hxx deleted file mode 100644 index afe6d134a829..000000000000 --- a/sd/source/ui/annotations/annotationtag.hxx +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#pragma once - -#include <vcl/vclevent.hxx> - -#include <smarttag.hxx> -#include "annotationwindow.hxx" - -namespace com::sun::star::office { class XAnnotation; } - -namespace sdr::annotation { class Annotation; } -namespace sd -{ -class View; -class AnnotationManagerImpl; - -class AnnotationTag final : public SmartTag -{ -public: - AnnotationTag( AnnotationManagerImpl& rManager, ::sd::View& rView, rtl::Reference<sdr::annotation::Annotation> const& xAnnotation, Color const & rColor, int nIndex, const vcl::Font& rFont ); - virtual ~AnnotationTag() override; - - /// @return true if the SmartTag handled the event. - virtual bool MouseButtonDown( const MouseEvent&, SmartHdl& ) override; - - /// @return true if the SmartTag consumes this event. - virtual bool KeyInput( const KeyEvent& rKEvt ) override; - - /// @return true if the SmartTag consumes this event. - virtual bool Command( const CommandEvent& rCEvt ) override; - - // callbacks from sdr view - virtual sal_Int32 GetMarkablePointCount() const override; - virtual sal_Int32 GetMarkedPointCount() const override; - virtual bool MarkPoint(SdrHdl& rHdl, bool bUnmark) override; - virtual void CheckPossibilities() override; - virtual bool MarkPoints(const ::tools::Rectangle* pRect, bool bUnmark) override; - - void Move( int nDX, int nDY ); - bool OnMove( const KeyEvent& rKEvt ); - - BitmapEx CreateAnnotationBitmap(bool); - - rtl::Reference<sdr::annotation::Annotation> const& GetAnnotation() const { return mxAnnotation; } - - void OpenPopup( bool bEdit ); - void ClosePopup(); - -private: - virtual void addCustomHandles( SdrHdlList& rHandlerList ) override; - virtual bool getContext( SdrViewContext& rContext ) override; - virtual void disposing() override; - virtual void select() override; - virtual void deselect() override; - - DECL_LINK( WindowEventHandler, VclWindowEvent&, void ); - DECL_LINK(PopupModeEndHdl, weld::Popover&, void); - - AnnotationManagerImpl& mrManager; - rtl::Reference<sdr::annotation::Annotation> mxAnnotation; - std::unique_ptr<AnnotationWindow> mpAnnotationWindow; - Color maColor; - int mnIndex; - const vcl::Font& mrFont; - Size maSize; - VclPtr<vcl::Window> mpListenWindow; - Point maMouseDownPos; -}; - -} // end of namespace sd - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index da1c4ca806e6..96a4e1c07100 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -1632,25 +1632,33 @@ static void ImplPDFExportComments( const uno::Reference< drawing::XDrawPage >& x aNote.maContents = xText->getString(); aNote.maModificationDate = xAnnotation->getDateTime(); auto* pAnnotation = dynamic_cast<sd::Annotation*>(xAnnotation.get()); - if (pAnnotation && pAnnotation->isFreeText()) - { - aNote.meType = vcl::pdf::PDFAnnotationSubType::FreeText; - } - if (pAnnotation && pAnnotation->hasCustomAnnotationMarker()) + + if (pAnnotation && pAnnotation->getCreationInfo().meType != sdr::annotation::AnnotationType::None) { - aNote.maPolygons = pAnnotation->getCustomAnnotationMarker().maPolygons; - aNote.maAnnotationColor = pAnnotation->getCustomAnnotationMarker().maLineColor; - aNote.maInteriorColor = pAnnotation->getCustomAnnotationMarker().maFillColor; - if (aNote.maPolygons.size() == 1) - { - auto const& rPolygon = aNote.maPolygons[0]; - aNote.meType = rPolygon.isClosed() - ? vcl::pdf::PDFAnnotationSubType::Polygon - : vcl::pdf::PDFAnnotationSubType::Polyline; - } - else if (aNote.maPolygons.size() > 1) + sdr::annotation::CreationInfo const& rCreation = pAnnotation->getCreationInfo(); + aNote.maPolygons = rCreation.maPolygons; + aNote.maAnnotationColor = rCreation.maColor; + aNote.maInteriorColor = rCreation.maFillColor; + aNote.mfWidth = rCreation.mnWidth; + switch (rCreation.meType) { - aNote.meType = vcl::pdf::PDFAnnotationSubType::Ink; + case sdr::annotation::AnnotationType::Square: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Square; break; + case sdr::annotation::AnnotationType::Circle: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Circle; break; + case sdr::annotation::AnnotationType::Polygon: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Polygon; break; + case sdr::annotation::AnnotationType::Ink: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Ink; break; + case sdr::annotation::AnnotationType::Highlight: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Highlight; break; + case sdr::annotation::AnnotationType::Line: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Line; break; + case sdr::annotation::AnnotationType::FreeText: + aNote.meType = vcl::pdf::PDFAnnotationSubType::FreeText; break; + default: + aNote.meType = vcl::pdf::PDFAnnotationSubType::Text; + break; } } diff --git a/sd/source/ui/unoidl/unopage.cxx b/sd/source/ui/unoidl/unopage.cxx index 6e0f2ad52b13..8f89dc0def6a 100644 --- a/sd/source/ui/unoidl/unopage.cxx +++ b/sd/source/ui/unoidl/unopage.cxx @@ -2529,7 +2529,9 @@ Reference< XAnnotation > SAL_CALL SdGenericDrawPage::createAndInsertAnnotation() if( !GetPage() ) throw DisposedException(); - return GetPage()->createAnnotation(); + auto xAnnotation = GetPage()->createAnnotation(); + GetPage()->addAnnotation(xAnnotation); + return xAnnotation; } void SAL_CALL SdGenericDrawPage::removeAnnotation(const Reference< XAnnotation > & annotation) diff --git a/sd/source/ui/view/drviews4.cxx b/sd/source/ui/view/drviews4.cxx index 83ffcc9be39b..7bd35adfb4c9 100644 --- a/sd/source/ui/view/drviews4.cxx +++ b/sd/source/ui/view/drviews4.cxx @@ -758,6 +758,9 @@ void DrawViewShell::Command(const CommandEvent& rCEvt, ::sd::Window* pWin) case SdrObjKind::Table: aPopupId = "table"; break; + case SdrObjKind::Annotation: + aPopupId = "annotation"; + break; default: ; } } diff --git a/sd/uiconfig/sdraw/popupmenu/annotation.xml b/sd/uiconfig/sdraw/popupmenu/annotation.xml new file mode 100644 index 000000000000..4bb3cb0bcdcb --- /dev/null +++ b/sd/uiconfig/sdraw/popupmenu/annotation.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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/. + * +--> +<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu"> + <menu:menuitem menu:id=".uno:ObjectTitleDescription"/> +</menu:menupopup> diff --git a/sd/uiconfig/simpress/popupmenu/annotation.xml b/sd/uiconfig/simpress/popupmenu/annotation.xml new file mode 100644 index 000000000000..4bb3cb0bcdcb --- /dev/null +++ b/sd/uiconfig/simpress/popupmenu/annotation.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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/. + * +--> +<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu"> + <menu:menuitem menu:id=".uno:ObjectTitleDescription"/> +</menu:menupopup> diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk index 5218e9582b43..7fe222959676 100644 --- a/svx/Library_svxcore.mk +++ b/svx/Library_svxcore.mk @@ -108,6 +108,7 @@ endif $(eval $(call gb_Library_add_exception_objects,svxcore,\ svx/source/annotation/Annotation \ svx/source/annotation/AnnotationEnumeration \ + svx/source/annotation/AnnotationObject \ svx/source/annotation/TextAPI \ svx/source/core/extedit \ svx/source/core/graphichelper \ diff --git a/svx/source/annotation/AnnotationObject.cxx b/svx/source/annotation/AnnotationObject.cxx new file mode 100644 index 000000000000..35dc4807e1b8 --- /dev/null +++ b/svx/source/annotation/AnnotationObject.cxx @@ -0,0 +1,209 @@ +/* -*- 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 <config_features.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <sal/log.hxx> +#include <svx/svdmodel.hxx> + +#include <svx/annotation/AnnotationObject.hxx> +#include <svx/annotation/ObjectAnnotationData.hxx> +#include <sdr/properties/rectangleproperties.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/sdtfsitm.hxx> +#include <svx/sdooitm.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/sdasitm.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/colritem.hxx> +#include <o3tl/unit_conversion.hxx> + +using namespace css; + +namespace sdr::annotation +{ +namespace +{ +OUString createInitials(OUString const& rName) +{ + OUStringBuffer sInitials; + + const sal_Unicode* pStr = rName.getStr(); + sal_Int32 nLength = rName.getLength(); + + while (nLength) + { + // skip whitespace + while (nLength && (*pStr <= ' ')) + { + nLength--; + pStr++; + } + + // take letter + if (nLength) + { + sInitials.append(*pStr); + nLength--; + pStr++; + } + + // skip letters until whitespace + while (nLength && (*pStr > ' ')) + { + nLength--; + pStr++; + } + } + + return sInitials.makeStringAndClear(); +} + +Color getColorLight(sal_uInt16 aAuthorIndex) +{ + if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + constexpr const auto constArrayLight + = std::to_array<Color>({ COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT, + COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT, + COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT }); + return constArrayLight[aAuthorIndex % constArrayLight.size()]; + } + + return COL_WHITE; +} +} + +AnnotationObject::AnnotationObject(SdrModel& rSdrModel) + : SdrRectObj(rSdrModel) +{ + setAsAnnotationObject(true); +} + +AnnotationObject::AnnotationObject(SdrModel& rSdrModel, AnnotationObject const& rSource) + : SdrRectObj(rSdrModel, rSource) +{ + setAsAnnotationObject(true); +} + +AnnotationObject::AnnotationObject(SdrModel& rSdrModel, tools::Rectangle const& rRectangle, + sdr::annotation::AnnotationViewData const& rAnnotationViewData) + : SdrRectObj(rSdrModel, rRectangle) + , maViewData(rAnnotationViewData) +{ + osl_atomic_increment(&m_refCount); + + const bool bUndo(rSdrModel.IsUndoEnabled()); + rSdrModel.EnableUndo(false); + MakeNameUnique(); + rSdrModel.EnableUndo(bUndo); + + osl_atomic_decrement(&m_refCount); + setAsAnnotationObject(true); +} + +void AnnotationObject::ApplyAnnotationName() +{ + if (mpAnnotationData->mxAnnotation) + { + OUString sInitials(mpAnnotationData->mxAnnotation->getInitials()); + if (sInitials.isEmpty()) + sInitials = createInitials(mpAnnotationData->mxAnnotation->getAuthor()); + SetText(sInitials + " " + OUString::number(maViewData.nIndex)); + } + else + { + SetText(u"Empty"_ustr); + } + + Color aColor(getColorLight(maViewData.nAuthorIndex)); + + SetMergedItem(XFillStyleItem(drawing::FillStyle_SOLID)); + SetMergedItem(XFillColorItem(OUString(), aColor)); + + Color aBorderColor(aColor); + if (aColor.IsDark()) + aBorderColor.IncreaseLuminance(32); + else + aBorderColor.DecreaseLuminance(32); + + SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID)); + SetMergedItem(XLineColorItem(OUString(), aBorderColor)); + SetMergedItem(XLineWidthItem(o3tl::convert(0, o3tl::Length::pt, o3tl::Length::mm100))); + + SetMergedItem(SvxFontHeightItem(o3tl::convert(10, o3tl::Length::pt, o3tl::Length::mm100), 100, + EE_CHAR_FONTHEIGHT)); + + SetMergedItem(SvxColorItem(aColor.IsDark() ? COL_WHITE : COL_BLACK, EE_CHAR_COLOR)); + + SetMergedItem(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_NONE)); + + SetMergedItem(makeSdrTextWordWrapItem(false)); + SetMergedItem(makeSdrTextAutoGrowWidthItem(true)); + SetMergedItem(makeSdrTextAutoGrowHeightItem(true)); +} + +AnnotationObject::~AnnotationObject() {} + +void AnnotationObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bMoveAllowed = true; + rInfo.bResizeFreeAllowed = false; + rInfo.bResizePropAllowed = false; + rInfo.bRotateFreeAllowed = false; + rInfo.bRotate90Allowed = false; + rInfo.bMirrorFreeAllowed = false; + rInfo.bMirror45Allowed = false; + rInfo.bMirror90Allowed = false; + rInfo.bTransparenceAllowed = false; + rInfo.bShearAllowed = false; + rInfo.bEdgeRadiusAllowed = false; + rInfo.bNoOrthoDesired = false; + rInfo.bNoContortion = false; + rInfo.bCanConvToPath = false; + rInfo.bCanConvToPoly = false; + rInfo.bCanConvToContour = false; + rInfo.bCanConvToPathLineToArea = false; + rInfo.bCanConvToPolyLineToArea = false; +} + +SdrObjKind AnnotationObject::GetObjIdentifier() const { return SdrObjKind::Annotation; } + +OUString AnnotationObject::TakeObjNameSingul() const +{ + OUString sName(u"Annotation"_ustr); + OUString aName(GetName()); + + if (!aName.isEmpty()) + sName += " '" + aName + "'"; + + return sName; +} + +OUString AnnotationObject::TakeObjNamePlural() const { return u"Annotations"_ustr; } + +rtl::Reference<SdrObject> AnnotationObject::CloneSdrObject(SdrModel& rTargetModel) const +{ + return new AnnotationObject(rTargetModel, *this); +} + +bool AnnotationObject::HasTextEdit() const { return false; } + +} // end sdr::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/unodraw/unopage.cxx b/svx/source/unodraw/unopage.cxx index fc613dd23f4a..9bf61e49af53 100644 --- a/svx/source/unodraw/unopage.cxx +++ b/svx/source/unodraw/unopage.cxx @@ -766,6 +766,9 @@ rtl::Reference<SvxShape> SvxDrawPage::CreateShapeByTypeAndInventor( SdrObjKind n case SdrObjKind::Table: pRet = new SvxTableShape( pObj ); break; + case SdrObjKind::Annotation: + pRet = new SvxShapeRect( pObj ); + break; default: // unknown 2D-object on page assert(false && "Not implemented Starone-Shape created"); pRet = new SvxShapeText( pObj ); diff --git a/svx/source/unodraw/unoprov.cxx b/svx/source/unodraw/unoprov.cxx index d210da214ee7..356894621c0a 100644 --- a/svx/source/unodraw/unoprov.cxx +++ b/svx/source/unodraw/unoprov.cxx @@ -822,6 +822,7 @@ const UHashMapImpl& GetUHashImpl() { "com.sun.star.drawing.AppletShape", SdrObjKind::OLE2Applet }, { "com.sun.star.drawing.CustomShape", SdrObjKind::CustomShape }, { "com.sun.star.drawing.MediaShape", SdrObjKind::Media }, + { "com.sun.star.drawing.AnnotationShape", SdrObjKind::Annotation }, { "com.sun.star.drawing.Shape3DSceneObject", SdrObjKind::E3D_Scene }, { "com.sun.star.drawing.Shape3DCubeObject", SdrObjKind::E3D_Cube }, diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx index 934c72c85cfb..5c3807817a6f 100644 --- a/svx/source/unodraw/unoshape.cxx +++ b/svx/source/unodraw/unoshape.cxx @@ -3184,6 +3184,7 @@ constexpr OUString sUNO_service_drawing_PolyLineShape = u"com.sun.star.drawi constexpr OUString sUNO_service_drawing_OpenBezierShape = u"com.sun.star.drawing.OpenBezierShape"_ustr; constexpr OUString sUNO_service_drawing_ClosedBezierShape = u"com.sun.star.drawing.ClosedBezierShape"_ustr; constexpr OUString sUNO_service_drawing_TextShape = u"com.sun.star.drawing.TextShape"_ustr; +constexpr OUString sUNO_service_drawing_AnnotationShape = u"com.sun.star.drawing.AnnotationShape"_ustr; constexpr OUString sUNO_service_drawing_GraphicObjectShape = u"com.sun.star.drawing.GraphicObjectShape"_ustr; constexpr OUString sUNO_service_drawing_OLE2Shape = u"com.sun.star.drawing.OLE2Shape"_ustr; constexpr OUString sUNO_service_drawing_PageShape = u"com.sun.star.drawing.PageShape"_ustr; @@ -3442,6 +3443,29 @@ uno::Sequence< OUString > SvxShape::_getSupportedServiceNames() sUNO_service_drawing_RotationDescriptor }; return aSvxShape_TextServices; } + case SdrObjKind::Annotation: + { + static const uno::Sequence<OUString> aSvxShape_AnnotationServices = { + sUNO_service_drawing_AnnotationShape, + + sUNO_service_drawing_Shape, + sUNO_service_drawing_FillProperties, + sUNO_service_drawing_LineProperties, + + sUNO_service_drawing_Text, + sUNO_service_drawing_TextProperties, + sUNO_service_style_ParagraphProperties, + sUNO_service_style_ParagraphPropertiesComplex, + sUNO_service_style_ParagraphPropertiesAsian, + sUNO_service_style_CharacterProperties, + sUNO_service_style_CharacterPropertiesComplex, + sUNO_service_style_CharacterPropertiesAsian, + + sUNO_service_drawing_ShadowProperties, + sUNO_service_drawing_RotationDescriptor + }; + return aSvxShape_AnnotationServices; + } case SdrObjKind::Graphic: { |