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 <oox/ppt/pptshape.hxx>
21 #include <oox/core/xmlfilterbase.hxx>
22 #include <drawingml/customshapeproperties.hxx>
23 #include <drawingml/textbody.hxx>
24 #include <drawingml/textparagraph.hxx>
25 #include <drawingml/textfield.hxx>
26 #include <editeng/flditem.hxx>
28 #include <com/sun/star/text/XTextField.hpp>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/drawing/XDrawPage.hpp>
33 #include <com/sun/star/drawing/XDrawPages.hpp>
34 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
35 #include <com/sun/star/drawing/XShapes.hpp>
36 #include <com/sun/star/text/XText.hpp>
37 #include <com/sun/star/document/XEventsSupplier.hpp>
38 #include <com/sun/star/container/XNameReplace.hpp>
39 #include <com/sun/star/presentation/ClickAction.hpp>
40 #include <basegfx/matrix/b2dhommatrix.hxx>
41 #include <sal/log.hxx>
42 #include <oox/ppt/slidepersist.hxx>
43 #include <oox/token/tokens.hxx>
44 #include <oox/token/properties.hxx>
45 #include <o3tl/string_view.hxx>
47 using namespace ::oox::core
;
48 using namespace ::oox::drawingml
;
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::awt
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::text
;
54 using namespace ::com::sun::star::drawing
;
55 using namespace ::com::sun::star::document
;
56 using namespace ::com::sun::star::container
;
57 using namespace ::com::sun::star::presentation
;
61 PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation
, const char* pServiceName
)
62 : Shape( pServiceName
)
63 , meShapeLocation( eShapeLocation
)
64 , mbReferenced( false )
65 , mbHasNoninheritedShapeProperties( false )
73 static const char* lclDebugSubType( sal_Int32 nType
)
98 return "unknown - please extend lclDebugSubType";
103 bool ShapeHasNoVisualPropertiesOnImport(const oox::ppt::PPTShape
& rPPTShape
)
105 return !rPPTShape
.hasNonInheritedShapeProperties()
106 && !rPPTShape
.hasShapeStyleRefs()
107 && !rPPTShape
.getTextBody()->hasVisualRunProperties()
108 && !rPPTShape
.getTextBody()->hasNoninheritedBodyProperties()
109 && !rPPTShape
.getTextBody()->hasListStyleOnImport()
110 && !rPPTShape
.getTextBody()->hasParagraphProperties();
114 oox::drawingml::TextListStylePtr
PPTShape::getSubTypeTextListStyle( const SlidePersist
& rSlidePersist
, sal_Int32 nSubType
)
116 oox::drawingml::TextListStylePtr pTextListStyle
;
118 SAL_INFO("oox.ppt", "subtype style: " << lclDebugSubType( nSubType
) );
124 pTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getTitleTextStyle() : rSlidePersist
.getTitleTextStyle();
129 if ( rSlidePersist
.isNotesPage() )
130 pTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getNotesTextStyle() : rSlidePersist
.getNotesTextStyle();
132 pTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getBodyTextStyle() : rSlidePersist
.getBodyTextStyle();
136 return pTextListStyle
;
139 bool PPTShape::IsPlaceHolderCandidate(const SlidePersist
& rSlidePersist
) const
141 if (meShapeLocation
!= Slide
)
143 if (rSlidePersist
.isNotesPage())
145 auto pTextBody
= getTextBody();
148 auto rParagraphs
= pTextBody
->getParagraphs();
149 if (rParagraphs
.size() != 1)
151 if (rParagraphs
.front()->getRuns().size() != 1)
153 // If the placeholder has a shape other than rectangle,
154 // we have to place it in the slide as a CustomShape.
155 if (!mpCustomShapePropertiesPtr
->representsDefaultShape())
157 return ShapeHasNoVisualPropertiesOnImport(*this);
160 void PPTShape::addShape(
161 oox::core::XmlFilterBase
& rFilterBase
,
162 const SlidePersist
& rSlidePersist
,
163 const oox::drawingml::Theme
* pTheme
,
164 const Reference
< XShapes
>& rxShapes
,
165 basegfx::B2DHomMatrix
& aTransformation
,
166 ::oox::drawingml::ShapeIdMap
* pShapeMap
)
168 SAL_INFO("oox.ppt","add shape id: " << msId
<< " location: " << ((meShapeLocation
== Master
) ? "master" : ((meShapeLocation
== Slide
) ? "slide" : ((meShapeLocation
== Layout
) ? "layout" : "other"))) << " subtype: " << mnSubType
<< " service: " << msServiceName
);
169 // only placeholder from layout are being inserted
170 if ( mnSubType
&& ( meShapeLocation
== Master
) )
173 OUString
sServiceName( msServiceName
);
174 if (sServiceName
.isEmpty())
178 oox::drawingml::TextListStylePtr aMasterTextListStyle
;
179 Reference
<lang::XMultiServiceFactory
> xServiceFact(rFilterBase
.getModel(), UNO_QUERY_THROW
);
180 bool bClearText
= false;
182 if (sServiceName
!= "com.sun.star.drawing.GraphicObjectShape" &&
183 sServiceName
!= "com.sun.star.drawing.OLE2Shape")
185 static constexpr OUString
sOutlinerShapeService(u
"com.sun.star.presentation.OutlinerShape"_ustr
);
186 SAL_INFO("oox.ppt","has master: " << std::hex
<< rSlidePersist
.getMasterPersist().get());
192 sServiceName
= "com.sun.star.presentation.TitleTextShape";
193 aMasterTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getTitleTextStyle() : rSlidePersist
.getTitleTextStyle();
198 if ((meShapeLocation
== Master
) || (meShapeLocation
== Layout
))
199 sServiceName
= OUString();
201 sServiceName
= "com.sun.star.presentation.SubtitleShape";
202 aMasterTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getBodyTextStyle() : rSlidePersist
.getBodyTextStyle();
208 sServiceName
= sOutlinerShapeService
;
209 if (getSubTypeIndex().has_value())
210 aMasterTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getBodyTextStyle() : rSlidePersist
.getBodyTextStyle();
215 if (rSlidePersist
.isNotesPage())
217 sServiceName
= "com.sun.star.presentation.NotesShape";
218 aMasterTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getNotesTextStyle() : rSlidePersist
.getNotesTextStyle();
222 sServiceName
= sOutlinerShapeService
;
223 aMasterTextListStyle
= rSlidePersist
.getMasterPersist() ? rSlidePersist
.getMasterPersist()->getBodyTextStyle() : rSlidePersist
.getBodyTextStyle();
228 if (IsPlaceHolderCandidate(rSlidePersist
))
230 TextRunPtr
& pTextRun
= getTextBody()->getParagraphs().front()->getRuns().front();
231 oox::drawingml::TextField
* pTextField
= dynamic_cast<oox::drawingml::TextField
*>(pTextRun
.get());
234 OUString aType
= pTextField
->getType();
235 if ( aType
.startsWith("datetime") )
237 SvxDateFormat eDateFormat
= drawingml::TextField::getLODateFormat(aType
);
238 SvxTimeFormat eTimeFormat
= drawingml::TextField::getLOTimeFormat(aType
);
239 Reference
< XPropertySet
> xPropertySet( rSlidePersist
.getPage(), UNO_QUERY
);
241 if( eDateFormat
!= SvxDateFormat::AppDefault
242 || eTimeFormat
!= SvxTimeFormat::AppDefault
)
244 // DateTimeFormat property looks for the date in 4 LSBs
245 // and looks for time format in the 4 bits after that
246 sal_Int32 nDateTimeFormat
= static_cast<sal_Int32
>(eDateFormat
) |
247 static_cast<sal_Int32
>(eTimeFormat
) << 4;
248 xPropertySet
->setPropertyValue( "IsDateTimeVisible", Any(true) );
249 xPropertySet
->setPropertyValue( "IsDateTimeFixed", Any(false) );
250 xPropertySet
->setPropertyValue( "DateTimeFormat", Any(nDateTimeFormat
) );
256 sServiceName
= "com.sun.star.presentation.DateTimeShape";
260 sServiceName
= "com.sun.star.presentation.HeaderShape";
264 if (IsPlaceHolderCandidate(rSlidePersist
))
266 const OUString
& rFooterText
= getTextBody()->toString();
268 if( !rFooterText
.isEmpty() )
270 // if it is possible to get the footer as a property the LO way,
271 // get it and discard the shape
272 Reference
< XPropertySet
> xPropertySet( rSlidePersist
.getPage(), UNO_QUERY
);
273 xPropertySet
->setPropertyValue( "IsFooterVisible", Any( true ) );
274 xPropertySet
->setPropertyValue( "FooterText", Any(rFooterText
) );
278 sServiceName
= "com.sun.star.presentation.FooterShape";
282 if (IsPlaceHolderCandidate(rSlidePersist
))
285 = getTextBody()->getParagraphs().front()->getRuns().front();
286 oox::drawingml::TextField
* pTextField
287 = dynamic_cast<oox::drawingml::TextField
*>(pTextRun
.get());
288 if (pTextField
&& pTextField
->getType() == "slidenum")
290 // if it is possible to get the slidenum placeholder as a property
291 // do that and discard the shape
292 Reference
<XPropertySet
> xPropertySet(rSlidePersist
.getPage(),
294 xPropertySet
->setPropertyValue("IsPageNumberVisible", Any(true));
298 sServiceName
= "com.sun.star.presentation.SlideNumberShape";
302 sServiceName
= "com.sun.star.presentation.PageShape";
305 if (meShapeLocation
== Layout
)
306 sServiceName
= sOutlinerShapeService
;
308 sServiceName
= "com.sun.star.presentation.ChartShape";
311 if (meShapeLocation
== Layout
)
312 sServiceName
= sOutlinerShapeService
;
314 sServiceName
= "com.sun.star.presentation.TableShape";
317 if (meShapeLocation
== Layout
)
318 sServiceName
= sOutlinerShapeService
;
320 sServiceName
= "com.sun.star.presentation.GraphicObjectShape";
323 if (meShapeLocation
== Layout
)
324 sServiceName
= sOutlinerShapeService
;
326 sServiceName
= "com.sun.star.presentation.MediaShape";
329 if (mnSubType
&& meShapeLocation
== Layout
)
330 sServiceName
= sOutlinerShapeService
;
335 // Since it is not possible to represent custom shaped placeholders in Impress
336 // Need to use service name css.drawing.CustomShape if they have a non default shape.
337 // This workaround has the drawback of them not really being processed as placeholders
338 // so it is only done for slide footers...
339 bool convertInSlideMode
= meShapeLocation
== Slide
&&
340 (mnSubType
== XML_sldNum
|| mnSubType
== XML_dt
|| mnSubType
== XML_ftr
|| mnSubType
== XML_body
);
341 bool convertInLayoutMode
= meShapeLocation
== Layout
&& (mnSubType
== XML_body
);
342 if ((convertInSlideMode
|| convertInLayoutMode
) && !mpCustomShapePropertiesPtr
->representsDefaultShape())
344 sServiceName
= "com.sun.star.drawing.CustomShape";
347 SAL_INFO("oox.ppt","shape service: " << sServiceName
);
349 if (mnSubType
&& getSubTypeIndex().has_value() && meShapeLocation
== Layout
)
351 oox::drawingml::ShapePtr pPlaceholder
= PPTShape::findPlaceholderByIndex( getSubTypeIndex().value(), rSlidePersist
.getShapes()->getChildren(), true );
353 pPlaceholder
= PPTShape::findPlaceholder( mnSubType
, 0, getSubTypeIndex(), rSlidePersist
.getShapes()->getChildren(), true );
356 if (maSize
.Width
== 0 || maSize
.Height
== 0) {
357 awt::Size aSize
= maSize
;
358 if (maSize
.Width
== 0)
359 aSize
.Width
= pPlaceholder
->getSize().Width
;
360 if (maSize
.Height
== 0)
361 aSize
.Height
= pPlaceholder
->getSize().Height
;
363 if (maPosition
.X
== 0 || maPosition
.Y
== 0) {
364 awt::Point aPosition
= maPosition
;
365 if (maPosition
.X
== 0)
366 aPosition
.X
= pPlaceholder
->getPosition().X
;
367 if (maPosition
.Y
== 0)
368 aPosition
.Y
= pPlaceholder
->getPosition().Y
;
369 setPosition( aPosition
);
375 // use placeholder index if possible
376 if (mnSubType
&& getSubTypeIndex().has_value() && rSlidePersist
.getMasterPersist())
378 oox::drawingml::ShapePtr pPlaceholder
= PPTShape::findPlaceholderByIndex(getSubTypeIndex().value(), rSlidePersist
.getMasterPersist()->getShapes()->getChildren());
379 // TODO: Check if this is required for non-notes slides as well...
380 if (rSlidePersist
.isNotesPage() && pPlaceholder
&& pPlaceholder
->getSubType() != getSubType())
381 pPlaceholder
.reset();
384 SAL_INFO("oox.ppt","found placeholder with index: " << getSubTypeIndex().value() << " and type: " << lclDebugSubType( mnSubType
));
385 PPTShape
* pPPTPlaceholder
= dynamic_cast< PPTShape
* >( pPlaceholder
.get() );
386 TextListStylePtr pNewTextListStyle
= std::make_shared
<TextListStyle
>();
388 if (pPlaceholder
->getTextBody()) {
390 pNewTextListStyle
->apply( pPlaceholder
->getTextBody()->getTextListStyle() );
391 if (pPlaceholder
->getMasterTextListStyle())
392 pNewTextListStyle
->apply( *pPlaceholder
->getMasterTextListStyle() );
394 // SAL_INFO("oox.ppt","placeholder body style");
395 // pPlaceholder->getTextBody()->getTextListStyle().dump();
396 // SAL_INFO("oox.ppt","master text list style");
397 // pPlaceholder->getMasterTextListStyle()->dump();
399 aMasterTextListStyle
= pNewTextListStyle
;
400 // SAL_INFO("oox.ppt","combined master text list style");
401 // aMasterTextListStyle->dump();
403 if (pPPTPlaceholder
&& pPPTPlaceholder
->mpPlaceholder
) {
404 SAL_INFO("oox.ppt","placeholder has parent placeholder: " << pPPTPlaceholder
->mpPlaceholder
->getId() << " type: " << lclDebugSubType( pPPTPlaceholder
->mpPlaceholder
->getSubType() ) << " index: " << pPPTPlaceholder
->mpPlaceholder
->getSubTypeIndex().value() );
405 SAL_INFO("oox.ppt","has textbody " << (pPPTPlaceholder
->mpPlaceholder
->getTextBody() != nullptr) );
406 TextListStylePtr pPlaceholderStyle
= getSubTypeTextListStyle( rSlidePersist
, pPPTPlaceholder
->mpPlaceholder
->getSubType() );
407 if (pPPTPlaceholder
->mpPlaceholder
->getTextBody())
408 pNewTextListStyle
->apply( pPPTPlaceholder
->mpPlaceholder
->getTextBody()->getTextListStyle() );
409 if (pPlaceholderStyle
) {
410 pNewTextListStyle
->apply( *pPlaceholderStyle
);
411 //pPlaceholderStyle->dump();
414 } else if (!mpPlaceholder
) {
415 aMasterTextListStyle
.reset();
417 SAL_INFO("oox.ppt","placeholder id: " << (pPlaceholder
? pPlaceholder
->getId() : "not found"));
420 if (!sServiceName
.isEmpty())
422 if (!aMasterTextListStyle
)
424 bool isOther
= !getTextBody() && sServiceName
!= "com.sun.star.drawing.GroupShape";
425 TextListStylePtr aSlideStyle
= isOther
? rSlidePersist
.getOtherTextStyle() : rSlidePersist
.getDefaultTextStyle();
426 // Combine from MasterSlide details as well.
427 if (rSlidePersist
.getMasterPersist())
429 aMasterTextListStyle
= isOther
? rSlidePersist
.getMasterPersist()->getOtherTextStyle() : rSlidePersist
.getMasterPersist()->getDefaultTextStyle();
431 aMasterTextListStyle
->apply( *aSlideStyle
);
435 aMasterTextListStyle
= aSlideStyle
;
439 if( aMasterTextListStyle
&& getTextBody() ) {
440 TextListStylePtr aCombinedTextListStyle
= std::make_shared
<TextListStyle
>();
442 aCombinedTextListStyle
->apply( *aMasterTextListStyle
);
444 if( mpPlaceholder
&& mpPlaceholder
->getTextBody() )
445 aCombinedTextListStyle
->apply( mpPlaceholder
->getTextBody()->getTextListStyle() );
446 aCombinedTextListStyle
->apply( getTextBody()->getTextListStyle() );
448 setMasterTextListStyle( aCombinedTextListStyle
);
450 setMasterTextListStyle( aMasterTextListStyle
);
452 Reference
< XShape
> xShape( createAndInsert( rFilterBase
, sServiceName
, pTheme
, rxShapes
, bClearText
, bool(mpPlaceholder
), aTransformation
, getFillProperties() ) );
454 // Apply text properties on placeholder text inside this placeholder shape
455 if (meShapeLocation
== Slide
&& mpPlaceholder
&& getTextBody() && getTextBody()->isEmpty())
457 Reference
< XText
> xText(mxShape
, UNO_QUERY
);
460 TextCharacterProperties aCharStyleProperties
;
461 getTextBody()->ApplyStyleEmpty(rFilterBase
, xText
, aCharStyleProperties
, mpMasterTextListStyle
);
466 // bnc#705982 - if optional model id reference is
467 // there, use that to obtain target shape
468 if (!msModelId
.isEmpty())
470 (*pShapeMap
)[ msModelId
] = shared_from_this();
472 else if (!msId
.isEmpty())
474 (*pShapeMap
)[ msId
] = shared_from_this();
478 // we will be losing whatever information there is in the footer placeholder on master/layout slides
479 // since they should have the "<footer>" textfield in them in order to make LibreOffice process them as expected
480 // likewise DateTime placeholder data on master/layout slides will be lost and replaced
481 if( (mnSubType
== XML_ftr
|| mnSubType
== XML_dt
) && meShapeLocation
!= Slide
)
484 if( mnSubType
== XML_ftr
)
485 aFieldType
= "com.sun.star.presentation.TextField.Footer";
487 aFieldType
= "com.sun.star.presentation.TextField.DateTime";
488 Reference
< XTextField
> xField( xServiceFact
->createInstance( aFieldType
), UNO_QUERY
);
489 Reference
< XText
> xText(mxShape
, UNO_QUERY
);
492 xText
->setString("");
493 Reference
< XTextCursor
> xTextCursor
= xText
->createTextCursor();
494 xText
->insertTextContent( xTextCursor
, xField
, false);
499 std::vector
<std::pair
<OUString
, Reference
<XShape
>>> aURLShapes
;
500 // if this is a group shape, we have to add also each child shape
501 Reference
<XShapes
> xShapes(xShape
, UNO_QUERY
);
504 // temporarily remember setting
505 NamedShapePairs
* pDiagramFontHeights(rFilterBase
.getDiagramFontHeights());
507 // for shapes unequal to FRAMETYPE_DIAGRAM do
508 // disable DiagramFontHeights recording
509 if (meFrameType
!= FRAMETYPE_DIAGRAM
)
510 rFilterBase
.setDiagramFontHeights(nullptr);
512 addChildren( rFilterBase
, *this, pTheme
, xShapes
, pShapeMap
, aTransformation
);
514 // restore remembered setting
515 rFilterBase
.setDiagramFontHeights(pDiagramFontHeights
);
517 for (size_t i
= 0; i
< this->getChildren().size(); i
++)
519 this->getChildren()[i
]->getShapeProperties().getProperty(PROP_URL
) >>= sURL
;
522 Reference
<XShape
> xChild
= this->getChildren()[i
]->getXShape();
523 aURLShapes
.push_back({ sURL
, xChild
});
528 if (meFrameType
== FRAMETYPE_DIAGRAM
)
530 keepDiagramCompatibilityInfo();
533 // Support advanced DiagramHelper
534 if (FRAMETYPE_DIAGRAM
== meFrameType
)
536 propagateDiagramHelper();
539 getShapeProperties().getProperty(PROP_URL
) >>= sURL
;
540 if (!sURL
.isEmpty() && !xShapes
.is())
541 aURLShapes
.push_back({ sURL
, xShape
});
543 if (!aURLShapes
.empty())
545 for (auto const& URLShape
: aURLShapes
)
547 Reference
<XEventsSupplier
> xEventsSupplier(URLShape
.second
, UNO_QUERY
);
548 if (!xEventsSupplier
.is())
551 Reference
<XNameReplace
> xEvents(xEventsSupplier
->getEvents());
555 OUString sAPIEventName
;
556 sal_Int32 nPropertyCount
= 2;
557 css::presentation::ClickAction meClickAction
;
558 uno::Sequence
<beans::PropertyValue
> aProperties
;
560 std::map
<OUString
, css::presentation::ClickAction
> ActionMap
= {
561 { "#action?jump=nextslide", ClickAction_NEXTPAGE
},
562 { "#action?jump=previousslide", ClickAction_PREVPAGE
},
563 { "#action?jump=firstslide", ClickAction_FIRSTPAGE
},
564 { "#action?jump=lastslide", ClickAction_LASTPAGE
},
565 { "#action?jump=endshow", ClickAction_STOPPRESENTATION
},
568 sURL
= URLShape
.first
;
569 std::map
<OUString
, css::presentation::ClickAction
>::const_iterator aIt
570 = ActionMap
.find(sURL
);
571 aIt
!= ActionMap
.end() ? meClickAction
= aIt
->second
572 : meClickAction
= ClickAction_BOOKMARK
;
574 // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same event
575 // so check here if it's a bookmark or a document
576 if (meClickAction
== ClickAction_BOOKMARK
)
578 if (!sURL
.startsWith("#"))
579 meClickAction
= ClickAction_DOCUMENT
;
582 sURL
= OUString::Concat("page")
583 + sURL
.subView(sURL
.lastIndexOf(' ') + 1);
588 aProperties
.realloc(nPropertyCount
);
589 beans::PropertyValue
* pProperties
= aProperties
.getArray();
591 pProperties
->Name
= "EventType";
592 pProperties
->Handle
= -1;
593 pProperties
->Value
<<= OUString("Presentation");
594 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
597 pProperties
->Name
= "ClickAction";
598 pProperties
->Handle
= -1;
599 pProperties
->Value
<<= meClickAction
;
600 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
603 switch (meClickAction
)
605 case ClickAction_BOOKMARK
:
606 case ClickAction_DOCUMENT
:
607 pProperties
->Name
= "Bookmark";
608 pProperties
->Handle
= -1;
609 pProperties
->Value
<<= sURL
;
610 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
616 sAPIEventName
= "OnClick";
617 xEvents
->replaceByName(sAPIEventName
, uno::Any(aProperties
));
622 catch (const Exception
&)
629 bool ShapeLocationIsMaster(oox::drawingml::Shape
*pInShape
)
631 PPTShape
* pShape
= dynamic_cast<PPTShape
*>(pInShape
);
632 return pShape
&& pShape
->getShapeLocation() == Master
;
636 // Function to find placeholder (ph) for a shape. No idea how MSO implements this, but
637 // this order seems to work quite well
638 // (probably it's unnecessary complicated / wrong. i.e. tdf#104202):
639 // 1. ph with nFirstSubType and the same oSubTypeIndex
640 // 2. ph with nFirstSubType
641 // 3. ph with nSecondSubType and the same oSubTypeIndex
642 // 4. ph with nSecondSubType
643 // 5. ph with the same oSubTypeIndex
645 oox::drawingml::ShapePtr
PPTShape::findPlaceholder( sal_Int32 nFirstSubType
, sal_Int32 nSecondSubType
,
646 const std::optional
< sal_Int32
>& oSubTypeIndex
, std::vector
< oox::drawingml::ShapePtr
>& rShapes
, bool bMasterOnly
)
652 : aChoice(5) // resize to 5
656 void add(const oox::drawingml::ShapePtr
& aShape
, sal_Int32 nFirstSubType
, sal_Int32 nSecondSubType
, const std::optional
< sal_Int32
>& oSubTypeIndex
)
662 const bool bSameFirstSubType
= aShape
->getSubType() == nFirstSubType
;
663 const bool bSameSecondSubType
= aShape
->getSubType() == nSecondSubType
;
664 const bool bSameIndex
= aShape
->getSubTypeIndex() == oSubTypeIndex
;
668 if (bSameIndex
&& bSameFirstSubType
)
670 else if (!bSameIndex
&& bSameFirstSubType
)
672 else if (bSameIndex
&& bSameSecondSubType
)
674 else if (!bSameIndex
&& bSameSecondSubType
)
680 if (aPrioIndex
!= -1)
682 if (!aChoice
.at(aPrioIndex
))
684 aChoice
.at(aPrioIndex
) = aShape
;
689 // return according to prio
690 oox::drawingml::ShapePtr
getByPrio() const
692 for (const oox::drawingml::ShapePtr
& aShape
: aChoice
)
700 return oox::drawingml::ShapePtr();
703 bool hasByPrio(size_t aIndex
) const
705 return bool(aChoice
.at(aIndex
));
709 std::vector
< oox::drawingml::ShapePtr
> aChoice
;
714 std::vector
< oox::drawingml::ShapePtr
>::reverse_iterator
aRevIter( rShapes
.rbegin() );
715 for (; aRevIter
!= rShapes
.rend(); ++aRevIter
)
718 if (!bMasterOnly
|| ShapeLocationIsMaster((*aRevIter
).get()))
720 const oox::drawingml::ShapePtr
& aShape
= *aRevIter
;
721 aPlaceholders
.add(aShape
, nFirstSubType
, nSecondSubType
, oSubTypeIndex
);
725 std::vector
< oox::drawingml::ShapePtr
>& rChildren
= (*aRevIter
)->getChildren();
726 if (!rChildren
.empty())
728 const oox::drawingml::ShapePtr aShape
= findPlaceholder( nFirstSubType
, nSecondSubType
, oSubTypeIndex
, rChildren
, bMasterOnly
);
731 aPlaceholders
.add(aShape
, nFirstSubType
, nSecondSubType
, oSubTypeIndex
);
735 if (aPlaceholders
.hasByPrio(0))
741 // return something according to prio
742 return aPlaceholders
.getByPrio();
745 oox::drawingml::ShapePtr
PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx
, std::vector
< oox::drawingml::ShapePtr
>& rShapes
, bool bMasterOnly
)
747 oox::drawingml::ShapePtr aShapePtr
;
749 std::vector
< oox::drawingml::ShapePtr
>::reverse_iterator
aRevIter( rShapes
.rbegin() );
750 while( aRevIter
!= rShapes
.rend() )
752 if ( (*aRevIter
)->getSubTypeIndex().has_value() && (*aRevIter
)->getSubTypeIndex().value() == nIdx
&&
753 ( !bMasterOnly
|| ShapeLocationIsMaster((*aRevIter
).get()) ) )
755 aShapePtr
= *aRevIter
;
758 std::vector
< oox::drawingml::ShapePtr
>& rChildren
= (*aRevIter
)->getChildren();
759 aShapePtr
= findPlaceholderByIndex( nIdx
, rChildren
, bMasterOnly
);
769 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */