1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <com/sun/star/geometry/RealPoint2D.hpp>
24 #include <com/sun/star/text/XTextCursor.hpp>
25 #include <com/sun/star/util/DateTime.hpp>
26 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <cppuhelper/implbase.hxx>
29 #include <sax/tools/converter.hxx>
30 #include <XMLNumberStylesImport.hxx>
31 #include <xmloff/xmlstyle.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/xmlnamespace.hxx>
34 #include "ximppage.hxx"
35 #include <animimp.hxx>
36 #include <XMLStringBufferImportContext.hxx>
37 #include <xmloff/xmlictxt.hxx>
38 #include "ximpstyl.hxx"
39 #include <xmloff/prstylei.hxx>
40 #include <PropertySetMerger.hxx>
41 #include <sal/log.hxx>
42 #include <comphelper/diagnose_ex.hxx>
44 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
45 #include <xmloff/xmluconv.hxx>
47 using namespace ::com::sun::star
;
48 using namespace ::xmloff::token
;
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
51 using namespace ::com::sun::star::text
;
52 using namespace ::com::sun::star::util
;
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::drawing
;
55 using namespace ::com::sun::star::container
;
56 using namespace ::com::sun::star::office
;
57 using namespace ::com::sun::star::xml::sax
;
58 using namespace ::com::sun::star::geometry
;
62 class DrawAnnotationContext
: public SvXMLImportContext
66 DrawAnnotationContext( SvXMLImport
& rImport
, const Reference
< xml::sax::XFastAttributeList
>& xAttrList
, const Reference
< XAnnotationAccess
>& xAnnotationAccess
);
68 virtual css::uno::Reference
< css::xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
69 sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& AttrList
) override
;
70 virtual void SAL_CALL
endFastElement(sal_Int32 nElement
) override
;
73 Reference
< XAnnotation
> mxAnnotation
;
74 Reference
< XTextCursor
> mxCursor
;
76 OUStringBuffer maAuthorBuffer
;
77 OUStringBuffer maInitialsBuffer
;
78 OUStringBuffer maDateBuffer
;
83 DrawAnnotationContext::DrawAnnotationContext( SvXMLImport
& rImport
, const Reference
< xml::sax::XFastAttributeList
>& xAttrList
, const Reference
< XAnnotationAccess
>& xAnnotationAccess
)
84 : SvXMLImportContext( rImport
)
85 , mxAnnotation( xAnnotationAccess
->createAndInsertAnnotation() )
87 if( !mxAnnotation
.is() )
90 RealPoint2D aPosition
;
93 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
95 switch( aIter
.getToken() )
97 case XML_ELEMENT(SVG
, XML_X
):
98 case XML_ELEMENT(SVG_COMPAT
, XML_X
):
101 GetImport().GetMM100UnitConverter().convertMeasureToCore(
103 aPosition
.X
= static_cast<double>(x
) / 100.0;
106 case XML_ELEMENT(SVG
, XML_Y
):
107 case XML_ELEMENT(SVG_COMPAT
, XML_Y
):
110 GetImport().GetMM100UnitConverter().convertMeasureToCore(
112 aPosition
.Y
= static_cast<double>(y
) / 100.0;
115 case XML_ELEMENT(SVG
, XML_WIDTH
):
116 case XML_ELEMENT(SVG_COMPAT
, XML_WIDTH
):
119 GetImport().GetMM100UnitConverter().convertMeasureToCore(
121 aSize
.Width
= static_cast<double>(w
) / 100.0;
124 case XML_ELEMENT(SVG
, XML_HEIGHT
):
125 case XML_ELEMENT(SVG_COMPAT
, XML_HEIGHT
):
128 GetImport().GetMM100UnitConverter().convertMeasureToCore(
130 aSize
.Height
= static_cast<double>(h
) / 100.0;
134 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
138 mxAnnotation
->setPosition( aPosition
);
139 mxAnnotation
->setSize( aSize
);
142 css::uno::Reference
< css::xml::sax::XFastContextHandler
> DrawAnnotationContext::createFastChildContext(
144 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
146 if( mxAnnotation
.is() )
148 if (nElement
== XML_ELEMENT(DC
, XML_CREATOR
) )
149 return new XMLStringBufferImportContext(GetImport(), maAuthorBuffer
);
150 else if( nElement
== XML_ELEMENT(DC
, XML_DATE
) )
151 return new XMLStringBufferImportContext(GetImport(), maDateBuffer
);
152 else if ( nElement
== XML_ELEMENT(TEXT
, XML_SENDER_INITIALS
)
153 || nElement
== XML_ELEMENT(LO_EXT
, XML_SENDER_INITIALS
)
154 || nElement
== XML_ELEMENT(META
, XML_CREATOR_INITIALS
))
156 return new XMLStringBufferImportContext(GetImport(), maInitialsBuffer
);
160 // create text cursor on demand
163 uno::Reference
< text::XText
> xText( mxAnnotation
->getTextRange() );
166 rtl::Reference
< XMLTextImportHelper
> xTxtImport
= GetImport().GetTextImport();
167 mxCursor
= xText
->createTextCursor();
169 xTxtImport
->SetCursor( mxCursor
);
173 // if we have a text cursor, lets try to import some text
176 auto p
= GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nElement
, xAttrList
);
182 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
186 void DrawAnnotationContext::endFastElement(sal_Int32
)
190 // delete addition newline
191 mxCursor
->gotoEnd( false );
192 mxCursor
->goLeft( 1, true );
193 mxCursor
->setString( "" );
196 GetImport().GetTextImport()->ResetCursor();
199 if( mxAnnotation
.is() )
201 mxAnnotation
->setAuthor( maAuthorBuffer
.makeStringAndClear() );
202 mxAnnotation
->setInitials( maInitialsBuffer
.makeStringAndClear() );
204 util::DateTime aDateTime
;
205 if (::sax::Converter::parseDateTime(aDateTime
, maDateBuffer
))
207 mxAnnotation
->setDateTime(aDateTime
);
209 maDateBuffer
.setLength(0);
214 SdXMLGenericPageContext::SdXMLGenericPageContext(
215 SvXMLImport
& rImport
,
216 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
,
217 Reference
< drawing::XShapes
> const & rShapes
)
218 : SvXMLImportContext( rImport
)
219 , mxShapes( rShapes
)
220 , mxAnnotationAccess( rShapes
, UNO_QUERY
)
222 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
224 if( aIter
.getToken() == XML_ELEMENT(DRAW
, XML_NAV_ORDER
) )
226 msNavOrder
= aIter
.toString();
232 SdXMLGenericPageContext::~SdXMLGenericPageContext()
236 void SdXMLGenericPageContext::startFastElement( sal_Int32
/*nElement*/, const Reference
< css::xml::sax::XFastAttributeList
>& )
238 GetImport().GetShapeImport()->pushGroupForPostProcessing( mxShapes
);
240 if( GetImport().IsFormsSupported() )
241 GetImport().GetFormImport()->startPage( Reference
< drawing::XDrawPage
>::query( mxShapes
) );
244 css::uno::Reference
< css::xml::sax::XFastContextHandler
> SdXMLGenericPageContext::createFastChildContext(
246 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
248 if( nElement
== XML_ELEMENT(PRESENTATION
, XML_ANIMATIONS
) )
250 return new XMLAnimationsContext( GetImport() );
252 else if( nElement
== XML_ELEMENT(OFFICE
, XML_FORMS
) )
254 if( GetImport().IsFormsSupported() )
255 return xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetImport() );
257 else if( nElement
== XML_ELEMENT(OFFICE
, XML_ANNOTATION
) || nElement
== XML_ELEMENT(OFFICE_EXT
, XML_ANNOTATION
) )
259 if( mxAnnotationAccess
.is() )
260 return new DrawAnnotationContext( GetImport(), xAttrList
, mxAnnotationAccess
);
264 // call GroupChildContext function at common ShapeImport
265 auto p
= XMLShapeImportHelper::CreateGroupChildContext(GetImport(), nElement
, xAttrList
, mxShapes
);
269 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
273 void SdXMLGenericPageContext::endFastElement(sal_Int32
)
275 GetImport().GetShapeImport()->popGroupAndPostProcess();
277 if( GetImport().IsFormsSupported() )
278 GetImport().GetFormImport()->endPage();
280 if( !maUseHeaderDeclName
.isEmpty() || !maUseFooterDeclName
.isEmpty() || !maUseDateTimeDeclName
.isEmpty() )
284 Reference
<beans::XPropertySet
> xSet(mxShapes
, uno::UNO_QUERY_THROW
);
285 Reference
< beans::XPropertySetInfo
> xInfo( xSet
->getPropertySetInfo() );
287 if( !maUseHeaderDeclName
.isEmpty() )
289 static constexpr OUString
aStrHeaderTextProp( u
"HeaderText"_ustr
);
290 if( xInfo
->hasPropertyByName( aStrHeaderTextProp
) )
291 xSet
->setPropertyValue( aStrHeaderTextProp
,
292 Any( GetSdImport().GetHeaderDecl( maUseHeaderDeclName
) ) );
295 if( !maUseFooterDeclName
.isEmpty() )
297 static constexpr OUString
aStrFooterTextProp( u
"FooterText"_ustr
);
298 if( xInfo
->hasPropertyByName( aStrFooterTextProp
) )
299 xSet
->setPropertyValue( aStrFooterTextProp
,
300 Any( GetSdImport().GetFooterDecl( maUseFooterDeclName
) ) );
303 if( !maUseDateTimeDeclName
.isEmpty() )
305 static constexpr OUString
aStrDateTimeTextProp( u
"DateTimeText"_ustr
);
306 if( xInfo
->hasPropertyByName( aStrDateTimeTextProp
) )
309 OUString aDateTimeFormat
;
310 const OUString
aText( GetSdImport().GetDateTimeDecl( maUseDateTimeDeclName
, bFixed
, aDateTimeFormat
) );
312 xSet
->setPropertyValue("IsDateTimeFixed",
317 xSet
->setPropertyValue( aStrDateTimeTextProp
, Any( aText
) );
319 else if( !aDateTimeFormat
.isEmpty() )
321 const SdXMLStylesContext
* pStyles
= dynamic_cast< const SdXMLStylesContext
* >( GetSdImport().GetShapeImport()->GetStylesContext() );
323 pStyles
= dynamic_cast< const SdXMLStylesContext
* >( GetSdImport().GetShapeImport()->GetAutoStylesContext() );
327 const SdXMLNumberFormatImportContext
* pSdNumStyle
=
328 dynamic_cast< const SdXMLNumberFormatImportContext
* >( pStyles
->FindStyleChildContext( XmlStyleFamily::DATA_STYLE
, aDateTimeFormat
, true ) );
332 xSet
->setPropertyValue("DateTimeFormat",
333 Any( pSdNumStyle
->GetDrawKey() ) );
340 catch(const uno::Exception
&)
342 TOOLS_WARN_EXCEPTION("xmloff.draw", "");
346 SetNavigationOrder();
349 void SdXMLGenericPageContext::SetStyle( OUString
const & rStyleName
)
351 // set PageProperties?
352 if(rStyleName
.isEmpty())
357 const SvXMLImportContext
* pContext
= GetSdImport().GetShapeImport()->GetAutoStylesContext();
359 if (const SdXMLStylesContext
* pStyles
= dynamic_cast<const SdXMLStylesContext
*>(pContext
))
361 const SvXMLStyleContext
* pStyle
= pStyles
->FindStyleChildContext(
362 XmlStyleFamily::SD_DRAWINGPAGE_ID
, rStyleName
);
364 if (const XMLPropStyleContext
* pPropStyle
= dynamic_cast<const XMLPropStyleContext
*>(pStyle
))
366 Reference
<beans::XPropertySet
> xPropSet1(mxShapes
, uno::UNO_QUERY
);
369 Reference
< beans::XPropertySet
> xPropSet( xPropSet1
);
370 Reference
< beans::XPropertySet
> xBackgroundSet
;
372 static constexpr OUString
aBackground(u
"Background"_ustr
);
373 if( xPropSet1
->getPropertySetInfo()->hasPropertyByName( aBackground
) )
375 Reference
< beans::XPropertySetInfo
> xInfo( xPropSet1
->getPropertySetInfo() );
376 if( xInfo
.is() && xInfo
->hasPropertyByName( aBackground
) )
378 Reference
< lang::XMultiServiceFactory
> xServiceFact(GetSdImport().GetModel(), uno::UNO_QUERY
);
379 if(xServiceFact
.is())
381 xBackgroundSet
.set(xServiceFact
->createInstance("com.sun.star.drawing.Background"), UNO_QUERY
);
385 if( xBackgroundSet
.is() )
386 xPropSet
= PropertySetMerger_CreateInstance( xPropSet1
, xBackgroundSet
);
391 const_cast<XMLPropStyleContext
*>(pPropStyle
)->FillPropertySet(xPropSet
);
393 if( xBackgroundSet
.is() )
394 xPropSet1
->setPropertyValue( aBackground
, uno::Any( xBackgroundSet
) );
400 catch (const uno::Exception
&)
402 TOOLS_WARN_EXCEPTION("xmloff.draw", "");
406 void SdXMLGenericPageContext::SetLayout()
408 // set PresentationPageLayout?
409 if(!GetSdImport().IsImpress() || maPageLayoutName
.isEmpty())
412 sal_Int32 nType
= -1;
414 const SvXMLImportContext
* pContext
= GetSdImport().GetShapeImport()->GetStylesContext();
416 if (const SdXMLStylesContext
* pStyles
= dynamic_cast<const SdXMLStylesContext
*>(pContext
))
418 const SvXMLStyleContext
* pStyle
= pStyles
->FindStyleChildContext( XmlStyleFamily::SD_PRESENTATIONPAGELAYOUT_ID
, maPageLayoutName
);
420 if (const SdXMLPresentationPageLayoutContext
* pLayout
= dynamic_cast<const SdXMLPresentationPageLayoutContext
*>(pStyle
))
422 nType
= pLayout
->GetTypeId();
428 Reference
< container::XNameAccess
> xPageLayouts( GetSdImport().getPageLayouts() );
429 if( xPageLayouts
.is() )
431 if( xPageLayouts
->hasByName( maPageLayoutName
) )
432 xPageLayouts
->getByName( maPageLayoutName
) >>= nType
;
439 Reference
<beans::XPropertySet
> xPropSet(mxShapes
, uno::UNO_QUERY
);
442 OUString
aPropName("Layout");
443 Reference
< beans::XPropertySetInfo
> xInfo( xPropSet
->getPropertySetInfo() );
444 if( xInfo
.is() && xInfo
->hasPropertyByName( aPropName
) )
445 xPropSet
->setPropertyValue(aPropName
, uno::Any( static_cast<sal_Int16
>(nType
) ) );
450 void SdXMLGenericPageContext::DeleteAllShapes()
452 // now delete all up-to-now contained shapes; they have been created
453 // when setting the presentation page layout.
454 while(mxShapes
->getCount())
456 Reference
< drawing::XShape
> xShape
;
457 uno::Any
aAny(mxShapes
->getByIndex(0));
463 mxShapes
->remove(xShape
);
468 void SdXMLGenericPageContext::SetPageMaster( OUString
const & rsPageMasterName
)
470 if (!GetSdImport().GetShapeImport()->GetStylesContext())
473 // look for PageMaster with this name
475 // #80012# GetStylesContext() replaced with GetAutoStylesContext()
476 const SvXMLStylesContext
* pAutoStyles
= GetSdImport().GetShapeImport()->GetAutoStylesContext();
478 const SvXMLStyleContext
* pStyle
= pAutoStyles
? pAutoStyles
->FindStyleChildContext(XmlStyleFamily::SD_PAGEMASTERCONTEXT_ID
, rsPageMasterName
) : nullptr;
480 const SdXMLPageMasterContext
* pPageMaster
= dynamic_cast<const SdXMLPageMasterContext
*>(pStyle
);
484 const SdXMLPageMasterStyleContext
* pPageMasterContext
= pPageMaster
->GetPageMasterStyle();
486 if (!pPageMasterContext
)
489 Reference
< drawing::XDrawPage
> xMasterPage(GetLocalShapesContext(), uno::UNO_QUERY
);
490 if (!xMasterPage
.is())
493 // set sizes for this masterpage
494 Reference
<beans::XPropertySet
> xPropSet(xMasterPage
, uno::UNO_QUERY
);
497 xPropSet
->setPropertyValue("BorderBottom", Any(pPageMasterContext
->GetBorderBottom()));
498 xPropSet
->setPropertyValue("BorderLeft", Any(pPageMasterContext
->GetBorderLeft()));
499 xPropSet
->setPropertyValue("BorderRight", Any(pPageMasterContext
->GetBorderRight()));
500 xPropSet
->setPropertyValue("BorderTop", Any(pPageMasterContext
->GetBorderTop()));
501 xPropSet
->setPropertyValue("Width", Any(pPageMasterContext
->GetWidth()));
502 xPropSet
->setPropertyValue("Height", Any(pPageMasterContext
->GetHeight()));
503 xPropSet
->setPropertyValue("Orientation", Any(pPageMasterContext
->GetOrientation()));
509 class XoNavigationOrderAccess
: public ::cppu::WeakImplHelper
< XIndexAccess
>
512 explicit XoNavigationOrderAccess( std::vector
< Reference
< XShape
> >& rShapes
);
515 virtual sal_Int32 SAL_CALL
getCount( ) override
;
516 virtual Any SAL_CALL
getByIndex( sal_Int32 Index
) override
;
519 virtual Type SAL_CALL
getElementType( ) override
;
520 virtual sal_Bool SAL_CALL
hasElements( ) override
;
523 std::vector
< Reference
< XShape
> > maShapes
;
528 XoNavigationOrderAccess::XoNavigationOrderAccess( std::vector
< Reference
< XShape
> >& rShapes
)
530 maShapes
.swap( rShapes
);
534 sal_Int32 SAL_CALL
XoNavigationOrderAccess::getCount( )
536 return static_cast< sal_Int32
>( maShapes
.size() );
539 Any SAL_CALL
XoNavigationOrderAccess::getByIndex( sal_Int32 Index
)
541 if( (Index
< 0) || (Index
> getCount()) )
542 throw IndexOutOfBoundsException();
544 return Any( maShapes
[Index
] );
548 Type SAL_CALL
XoNavigationOrderAccess::getElementType( )
550 return cppu::UnoType
<XShape
>::get();
553 sal_Bool SAL_CALL
XoNavigationOrderAccess::hasElements( )
555 return !maShapes
.empty();
558 void SdXMLGenericPageContext::SetNavigationOrder()
560 if( msNavOrder
.isEmpty() )
566 const sal_uInt32 nCount
= static_cast< sal_uInt32
>( mxShapes
->getCount() );
567 std::vector
< Reference
< XShape
> > aShapes( nCount
);
569 ::comphelper::UnoInterfaceToUniqueIdentifierMapper
& rIdMapper
= GetSdImport().getInterfaceToIdentifierMapper();
570 SvXMLTokenEnumerator
aEnumerator( msNavOrder
);
571 std::u16string_view sId
;
572 for( nIndex
= 0; nIndex
< nCount
; ++nIndex
)
574 if( !aEnumerator
.getNextToken(sId
) )
577 aShapes
[nIndex
].set( rIdMapper
.getReference( OUString(sId
) ), UNO_QUERY
);
580 for( nIndex
= 0; nIndex
< nCount
; ++nIndex
)
582 if( !aShapes
[nIndex
].is() )
584 OSL_FAIL("xmloff::SdXMLGenericPageContext::SetNavigationOrder(), draw:nav-order attribute incomplete!");
590 Reference
< XPropertySet
> xSet( mxShapes
, UNO_QUERY_THROW
);
591 xSet
->setPropertyValue("NavigationOrder", Any( Reference
< XIndexAccess
>( new XoNavigationOrderAccess( aShapes
) ) ) );
593 catch(const uno::Exception
&)
595 TOOLS_WARN_EXCEPTION("xmloff.draw",
596 "unexpected exception caught while importing shape navigation order!");
600 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */