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 <tools/diagnose_ex.h>
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 SvXMLImportContextRef
CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const css::uno::Reference
< css::xml::sax::XAttributeList
>& xAttrList
) override
;
71 virtual void SAL_CALL
endFastElement(sal_Int32 nElement
) override
;
74 Reference
< XAnnotation
> mxAnnotation
;
75 Reference
< XTextCursor
> mxCursor
;
77 OUStringBuffer maAuthorBuffer
;
78 OUStringBuffer maInitialsBuffer
;
79 OUStringBuffer maDateBuffer
;
84 DrawAnnotationContext::DrawAnnotationContext( SvXMLImport
& rImport
, const Reference
< xml::sax::XFastAttributeList
>& xAttrList
, const Reference
< XAnnotationAccess
>& xAnnotationAccess
)
85 : SvXMLImportContext( rImport
)
86 , mxAnnotation( xAnnotationAccess
->createAndInsertAnnotation() )
88 if( !mxAnnotation
.is() )
91 RealPoint2D aPosition
;
94 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
96 OUString sValue
= aIter
.toString();
98 switch( aIter
.getToken() )
100 case XML_ELEMENT(SVG
, XML_X
):
101 case XML_ELEMENT(SVG_COMPAT
, XML_X
):
104 GetImport().GetMM100UnitConverter().convertMeasureToCore(
106 aPosition
.X
= static_cast<double>(x
) / 100.0;
109 case XML_ELEMENT(SVG
, XML_Y
):
110 case XML_ELEMENT(SVG_COMPAT
, XML_Y
):
113 GetImport().GetMM100UnitConverter().convertMeasureToCore(
115 aPosition
.Y
= static_cast<double>(y
) / 100.0;
118 case XML_ELEMENT(SVG
, XML_WIDTH
):
119 case XML_ELEMENT(SVG_COMPAT
, XML_WIDTH
):
122 GetImport().GetMM100UnitConverter().convertMeasureToCore(
124 aSize
.Width
= static_cast<double>(w
) / 100.0;
127 case XML_ELEMENT(SVG
, XML_HEIGHT
):
128 case XML_ELEMENT(SVG_COMPAT
, XML_HEIGHT
):
131 GetImport().GetMM100UnitConverter().convertMeasureToCore(
133 aSize
.Height
= static_cast<double>(h
) / 100.0;
137 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
141 mxAnnotation
->setPosition( aPosition
);
142 mxAnnotation
->setSize( aSize
);
145 css::uno::Reference
< css::xml::sax::XFastContextHandler
> DrawAnnotationContext::createFastChildContext(
147 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& /*xAttrList*/ )
149 if( mxAnnotation
.is() )
151 if (IsTokenInNamespace(nElement
, XML_NAMESPACE_DC
))
153 if( (nElement
& TOKEN_MASK
) == XML_CREATOR
)
154 return new XMLStringBufferImportContext(GetImport(), maAuthorBuffer
);
155 else if( (nElement
& TOKEN_MASK
) == XML_DATE
)
156 return new XMLStringBufferImportContext(GetImport(), maDateBuffer
);
158 else if ( nElement
== XML_ELEMENT(TEXT
, XML_SENDER_INITIALS
)
159 || nElement
== XML_ELEMENT(LO_EXT
, XML_SENDER_INITIALS
)
160 || nElement
== XML_ELEMENT(META
, XML_CREATOR_INITIALS
))
162 return new XMLStringBufferImportContext(GetImport(), maInitialsBuffer
);
168 SvXMLImportContextRef
DrawAnnotationContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
)
170 SvXMLImportContextRef xContext
;
172 if( mxAnnotation
.is() )
174 if( XML_NAMESPACE_DC
== nPrefix
)
176 // handled in createFastChildContext
178 else if (((XML_NAMESPACE_TEXT
== nPrefix
|| XML_NAMESPACE_LO_EXT
== nPrefix
)
179 && IsXMLToken(rLocalName
, XML_SENDER_INITIALS
))
180 || (XML_NAMESPACE_META
== nPrefix
181 && IsXMLToken(rLocalName
, XML_CREATOR_INITIALS
)))
183 // handled in createFastChildContext
187 // create text cursor on demand
190 uno::Reference
< text::XText
> xText( mxAnnotation
->getTextRange() );
193 rtl::Reference
< XMLTextImportHelper
> xTxtImport
= GetImport().GetTextImport();
194 mxCursor
= xText
->createTextCursor();
196 xTxtImport
->SetCursor( mxCursor
);
200 // if we have a text cursor, lets try to import some text
203 xContext
= GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nPrefix
, rLocalName
, xAttrList
);
211 void DrawAnnotationContext::endFastElement(sal_Int32
)
215 // delete addition newline
216 mxCursor
->gotoEnd( false );
217 mxCursor
->goLeft( 1, true );
218 mxCursor
->setString( "" );
221 GetImport().GetTextImport()->ResetCursor();
224 if( mxAnnotation
.is() )
226 mxAnnotation
->setAuthor( maAuthorBuffer
.makeStringAndClear() );
227 mxAnnotation
->setInitials( maInitialsBuffer
.makeStringAndClear() );
229 util::DateTime aDateTime
;
230 if (::sax::Converter::parseDateTime(aDateTime
,
231 maDateBuffer
.makeStringAndClear()))
233 mxAnnotation
->setDateTime(aDateTime
);
239 SdXMLGenericPageContext::SdXMLGenericPageContext(
240 SvXMLImport
& rImport
,
241 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
,
242 Reference
< drawing::XShapes
> const & rShapes
)
243 : SvXMLImportContext( rImport
)
244 , mxShapes( rShapes
)
245 , mxAnnotationAccess( rShapes
, UNO_QUERY
)
247 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
249 if( aIter
.getToken() == XML_ELEMENT(DRAW
, XML_NAV_ORDER
) )
251 msNavOrder
= aIter
.toString();
257 SdXMLGenericPageContext::~SdXMLGenericPageContext()
261 void SdXMLGenericPageContext::startFastElement( sal_Int32
/*nElement*/, const Reference
< css::xml::sax::XFastAttributeList
>& )
263 GetImport().GetShapeImport()->pushGroupForPostProcessing( mxShapes
);
265 if( GetImport().IsFormsSupported() )
266 GetImport().GetFormImport()->startPage( Reference
< drawing::XDrawPage
>::query( mxShapes
) );
269 css::uno::Reference
< css::xml::sax::XFastContextHandler
> SdXMLGenericPageContext::createFastChildContext(
271 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
273 if( nElement
== XML_ELEMENT(PRESENTATION
, XML_ANIMATIONS
) )
275 return new XMLAnimationsContext( GetImport() );
277 else if( nElement
== XML_ELEMENT(OFFICE
, XML_ANNOTATION
) || nElement
== XML_ELEMENT(OFFICE_EXT
, XML_ANNOTATION
) )
279 if( mxAnnotationAccess
.is() )
280 return new DrawAnnotationContext( GetImport(), xAttrList
, mxAnnotationAccess
);
285 SvXMLImportContextRef
SdXMLGenericPageContext::CreateChildContext( sal_uInt16 nPrefix
,
286 const OUString
& rLocalName
,
287 const Reference
< xml::sax::XAttributeList
>& xAttrList
)
289 SvXMLImportContextRef xContext
;
291 if( nPrefix
== XML_NAMESPACE_PRESENTATION
&& IsXMLToken( rLocalName
, XML_ANIMATIONS
) )
293 // handled in createFastChildContext
295 else if( nPrefix
== XML_NAMESPACE_OFFICE
&& IsXMLToken( rLocalName
, XML_FORMS
) )
297 if( GetImport().IsFormsSupported() )
298 xContext
= xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetImport() );
300 else if( ((nPrefix
== XML_NAMESPACE_OFFICE
) || (nPrefix
== XML_NAMESPACE_OFFICE_EXT
)) && IsXMLToken( rLocalName
, XML_ANNOTATION
) )
302 // handled in createFastChildContext
306 // call GroupChildContext function at common ShapeImport
307 xContext
= GetImport().GetShapeImport()->CreateGroupChildContext(
308 GetImport(), nPrefix
, rLocalName
, xAttrList
, mxShapes
);
314 void SdXMLGenericPageContext::endFastElement(sal_Int32
)
316 GetImport().GetShapeImport()->popGroupAndPostProcess();
318 if( GetImport().IsFormsSupported() )
319 GetImport().GetFormImport()->endPage();
321 if( !maUseHeaderDeclName
.isEmpty() || !maUseFooterDeclName
.isEmpty() || !maUseDateTimeDeclName
.isEmpty() )
325 Reference
<beans::XPropertySet
> xSet(mxShapes
, uno::UNO_QUERY_THROW
);
326 Reference
< beans::XPropertySetInfo
> xInfo( xSet
->getPropertySetInfo() );
328 if( !maUseHeaderDeclName
.isEmpty() )
330 const OUString
aStrHeaderTextProp( "HeaderText" );
331 if( xInfo
->hasPropertyByName( aStrHeaderTextProp
) )
332 xSet
->setPropertyValue( aStrHeaderTextProp
,
333 makeAny( GetSdImport().GetHeaderDecl( maUseHeaderDeclName
) ) );
336 if( !maUseFooterDeclName
.isEmpty() )
338 const OUString
aStrFooterTextProp( "FooterText" );
339 if( xInfo
->hasPropertyByName( aStrFooterTextProp
) )
340 xSet
->setPropertyValue( aStrFooterTextProp
,
341 makeAny( GetSdImport().GetFooterDecl( maUseFooterDeclName
) ) );
344 if( !maUseDateTimeDeclName
.isEmpty() )
346 const OUString
aStrDateTimeTextProp( "DateTimeText" );
347 if( xInfo
->hasPropertyByName( aStrDateTimeTextProp
) )
350 OUString aDateTimeFormat
;
351 const OUString
aText( GetSdImport().GetDateTimeDecl( maUseDateTimeDeclName
, bFixed
, aDateTimeFormat
) );
353 xSet
->setPropertyValue("IsDateTimeFixed",
358 xSet
->setPropertyValue( aStrDateTimeTextProp
, makeAny( aText
) );
360 else if( !aDateTimeFormat
.isEmpty() )
362 const SdXMLStylesContext
* pStyles
= dynamic_cast< const SdXMLStylesContext
* >( GetSdImport().GetShapeImport()->GetStylesContext() );
364 pStyles
= dynamic_cast< const SdXMLStylesContext
* >( GetSdImport().GetShapeImport()->GetAutoStylesContext() );
368 const SdXMLNumberFormatImportContext
* pSdNumStyle
=
369 dynamic_cast< const SdXMLNumberFormatImportContext
* >( pStyles
->FindStyleChildContext( XmlStyleFamily::DATA_STYLE
, aDateTimeFormat
, true ) );
373 xSet
->setPropertyValue("DateTimeFormat",
374 makeAny( pSdNumStyle
->GetDrawKey() ) );
381 catch(const uno::Exception
&)
383 TOOLS_WARN_EXCEPTION("xmloff.draw", "");
387 SetNavigationOrder();
390 void SdXMLGenericPageContext::SetStyle( OUString
const & rStyleName
)
392 // set PageProperties?
393 if(rStyleName
.isEmpty())
398 const SvXMLImportContext
* pContext
= GetSdImport().GetShapeImport()->GetAutoStylesContext();
400 if (const SdXMLStylesContext
* pStyles
= dynamic_cast<const SdXMLStylesContext
*>(pContext
))
402 const SvXMLStyleContext
* pStyle
= pStyles
->FindStyleChildContext(
403 XmlStyleFamily::SD_DRAWINGPAGE_ID
, rStyleName
);
405 if (const XMLPropStyleContext
* pPropStyle
= dynamic_cast<const XMLPropStyleContext
*>(pStyle
))
407 Reference
<beans::XPropertySet
> xPropSet1(mxShapes
, uno::UNO_QUERY
);
410 Reference
< beans::XPropertySet
> xPropSet( xPropSet1
);
411 Reference
< beans::XPropertySet
> xBackgroundSet
;
413 const OUString
aBackground("Background");
414 if( xPropSet1
->getPropertySetInfo()->hasPropertyByName( aBackground
) )
416 Reference
< beans::XPropertySetInfo
> xInfo( xPropSet1
->getPropertySetInfo() );
417 if( xInfo
.is() && xInfo
->hasPropertyByName( aBackground
) )
419 Reference
< lang::XMultiServiceFactory
> xServiceFact(GetSdImport().GetModel(), uno::UNO_QUERY
);
420 if(xServiceFact
.is())
422 xBackgroundSet
.set(xServiceFact
->createInstance("com.sun.star.drawing.Background"), UNO_QUERY
);
426 if( xBackgroundSet
.is() )
427 xPropSet
= PropertySetMerger_CreateInstance( xPropSet1
, xBackgroundSet
);
432 const_cast<XMLPropStyleContext
*>(pPropStyle
)->FillPropertySet(xPropSet
);
434 if( xBackgroundSet
.is() )
435 xPropSet1
->setPropertyValue( aBackground
, uno::makeAny( xBackgroundSet
) );
441 catch (const uno::Exception
&)
443 TOOLS_WARN_EXCEPTION("xmloff.draw", "");
447 void SdXMLGenericPageContext::SetLayout()
449 // set PresentationPageLayout?
450 if(!GetSdImport().IsImpress() || maPageLayoutName
.isEmpty())
453 sal_Int32 nType
= -1;
455 const SvXMLImportContext
* pContext
= GetSdImport().GetShapeImport()->GetStylesContext();
457 if (const SdXMLStylesContext
* pStyles
= dynamic_cast<const SdXMLStylesContext
*>(pContext
))
459 const SvXMLStyleContext
* pStyle
= pStyles
->FindStyleChildContext( XmlStyleFamily::SD_PRESENTATIONPAGELAYOUT_ID
, maPageLayoutName
);
461 if (const SdXMLPresentationPageLayoutContext
* pLayout
= dynamic_cast<const SdXMLPresentationPageLayoutContext
*>(pStyle
))
463 nType
= pLayout
->GetTypeId();
469 Reference
< container::XNameAccess
> xPageLayouts( GetSdImport().getPageLayouts() );
470 if( xPageLayouts
.is() )
472 if( xPageLayouts
->hasByName( maPageLayoutName
) )
473 xPageLayouts
->getByName( maPageLayoutName
) >>= nType
;
480 Reference
<beans::XPropertySet
> xPropSet(mxShapes
, uno::UNO_QUERY
);
483 OUString
aPropName("Layout");
484 Reference
< beans::XPropertySetInfo
> xInfo( xPropSet
->getPropertySetInfo() );
485 if( xInfo
.is() && xInfo
->hasPropertyByName( aPropName
) )
486 xPropSet
->setPropertyValue(aPropName
, uno::makeAny( static_cast<sal_Int16
>(nType
) ) );
491 void SdXMLGenericPageContext::DeleteAllShapes()
493 // now delete all up-to-now contained shapes; they have been created
494 // when setting the presentation page layout.
495 while(mxShapes
->getCount())
497 Reference
< drawing::XShape
> xShape
;
498 uno::Any
aAny(mxShapes
->getByIndex(0));
504 mxShapes
->remove(xShape
);
509 void SdXMLGenericPageContext::SetPageMaster( OUString
const & rsPageMasterName
)
511 if (!GetSdImport().GetShapeImport()->GetStylesContext())
514 // look for PageMaster with this name
516 // #80012# GetStylesContext() replaced with GetAutoStylesContext()
517 const SvXMLStylesContext
* pAutoStyles
= GetSdImport().GetShapeImport()->GetAutoStylesContext();
519 const SvXMLStyleContext
* pStyle
= pAutoStyles
? pAutoStyles
->FindStyleChildContext(XmlStyleFamily::SD_PAGEMASTERCONTEXT_ID
, rsPageMasterName
) : nullptr;
521 const SdXMLPageMasterContext
* pPageMaster
= dynamic_cast<const SdXMLPageMasterContext
*>(pStyle
);
525 const SdXMLPageMasterStyleContext
* pPageMasterContext
= pPageMaster
->GetPageMasterStyle();
527 if (!pPageMasterContext
)
530 Reference
< drawing::XDrawPage
> xMasterPage(GetLocalShapesContext(), uno::UNO_QUERY
);
531 if (!xMasterPage
.is())
534 // set sizes for this masterpage
535 Reference
<beans::XPropertySet
> xPropSet(xMasterPage
, uno::UNO_QUERY
);
538 xPropSet
->setPropertyValue("BorderBottom", Any(pPageMasterContext
->GetBorderBottom()));
539 xPropSet
->setPropertyValue("BorderLeft", Any(pPageMasterContext
->GetBorderLeft()));
540 xPropSet
->setPropertyValue("BorderRight", Any(pPageMasterContext
->GetBorderRight()));
541 xPropSet
->setPropertyValue("BorderTop", Any(pPageMasterContext
->GetBorderTop()));
542 xPropSet
->setPropertyValue("Width", Any(pPageMasterContext
->GetWidth()));
543 xPropSet
->setPropertyValue("Height", Any(pPageMasterContext
->GetHeight()));
544 xPropSet
->setPropertyValue("Orientation", Any(pPageMasterContext
->GetOrientation()));
550 class XoNavigationOrderAccess
: public ::cppu::WeakImplHelper
< XIndexAccess
>
553 explicit XoNavigationOrderAccess( std::vector
< Reference
< XShape
> >& rShapes
);
556 virtual sal_Int32 SAL_CALL
getCount( ) override
;
557 virtual Any SAL_CALL
getByIndex( sal_Int32 Index
) override
;
560 virtual Type SAL_CALL
getElementType( ) override
;
561 virtual sal_Bool SAL_CALL
hasElements( ) override
;
564 std::vector
< Reference
< XShape
> > maShapes
;
569 XoNavigationOrderAccess::XoNavigationOrderAccess( std::vector
< Reference
< XShape
> >& rShapes
)
571 maShapes
.swap( rShapes
);
575 sal_Int32 SAL_CALL
XoNavigationOrderAccess::getCount( )
577 return static_cast< sal_Int32
>( maShapes
.size() );
580 Any SAL_CALL
XoNavigationOrderAccess::getByIndex( sal_Int32 Index
)
582 if( (Index
< 0) || (Index
> getCount()) )
583 throw IndexOutOfBoundsException();
585 return Any( maShapes
[Index
] );
589 Type SAL_CALL
XoNavigationOrderAccess::getElementType( )
591 return cppu::UnoType
<XShape
>::get();
594 sal_Bool SAL_CALL
XoNavigationOrderAccess::hasElements( )
596 return !maShapes
.empty();
599 void SdXMLGenericPageContext::SetNavigationOrder()
601 if( msNavOrder
.isEmpty() )
607 const sal_uInt32 nCount
= static_cast< sal_uInt32
>( mxShapes
->getCount() );
608 std::vector
< Reference
< XShape
> > aShapes( nCount
);
610 ::comphelper::UnoInterfaceToUniqueIdentifierMapper
& rIdMapper
= GetSdImport().getInterfaceToIdentifierMapper();
611 SvXMLTokenEnumerator
aEnumerator( msNavOrder
);
613 for( nIndex
= 0; nIndex
< nCount
; ++nIndex
)
615 if( !aEnumerator
.getNextToken(sId
) )
618 aShapes
[nIndex
].set( rIdMapper
.getReference( sId
), UNO_QUERY
);
621 for( nIndex
= 0; nIndex
< nCount
; ++nIndex
)
623 if( !aShapes
[nIndex
].is() )
625 OSL_FAIL("xmloff::SdXMLGenericPageContext::SetNavigationOrder(), draw:nav-order attribute incomplete!");
631 Reference
< XPropertySet
> xSet( mxShapes
, UNO_QUERY_THROW
);
632 xSet
->setPropertyValue("NavigationOrder", Any( Reference
< XIndexAccess
>( new XoNavigationOrderAccess( aShapes
) ) ) );
634 catch(const uno::Exception
&)
636 TOOLS_WARN_EXCEPTION("xmloff.draw",
637 "unexpected exception caught while importing shape navigation order!");
641 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */