1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <memory>
23 #include <string_view>
24 #include <utility>
25 
26 #include <com/sun/star/style/XStyle.hpp>
27 #include <com/sun/star/presentation/ClickAction.hpp>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/beans/PropertyState.hpp>
30 #include <rtl/ustrbuf.hxx>
31 #include <svl/itemprop.hxx>
32 #include <svl/style.hxx>
33 #include <svx/svdpool.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/app.hxx>
36 #include <svtools/unoimap.hxx>
37 #include <svtools/unoevent.hxx>
38 #include <sfx2/bindings.hxx>
39 #include <sfx2/event.hxx>
40 #include <sfx2/sfxsids.hrc>
41 #include <comphelper/extract.hxx>
42 #include <cppuhelper/implbase.hxx>
43 #include <cppuhelper/supportsservice.hxx>
44 #include <svx/unoshape.hxx>
45 #include <svx/svdotext.hxx>
46 #include <svx/unoapi.hxx>
47 #include <svx/svdopath.hxx>
48 #include <svx/svdoole2.hxx>
49 #include <svx/svdograf.hxx>
50 #include <svx/ImageMapInfo.hxx>
51 #include <filter/msfilter/msdffimp.hxx>
52 #include <svl/instrm.hxx>
53 #include <editeng/outlobj.hxx>
54 #include <Outliner.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <svx/svdogrp.hxx>
57 #include <o3tl/typed_flags_set.hxx>
58 #include <vcl/svapp.hxx>
59 #include <tools/debug.hxx>
60 
61 #include <anminfo.hxx>
62 #include "unoobj.hxx"
63 #include <unoprnms.hxx>
64 #include <unomodel.hxx>
65 #include <drawdoc.hxx>
66 #include <sdmod.hxx>
67 #include <sdpage.hxx>
68 #include <ViewShell.hxx>
69 #include <unopage.hxx>
70 #include <DrawDocShell.hxx>
71 #include <EffectMigration.hxx>
72 
73 using namespace ::sd;
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::presentation;
76 using namespace ::com::sun::star::animations;
77 
78 using ::com::sun::star::uno::Any;
79 using ::com::sun::star::drawing::XShape;
80 
81 #define WID_EFFECT          1
82 #define WID_SPEED           2
83 #define WID_TEXTEFFECT      3
84 #define WID_BOOKMARK        4
85 #define WID_CLICKACTION     5
86 #define WID_PLAYFULL        6
87 #define WID_SOUNDFILE       7
88 #define WID_SOUNDON         8
89 #define WID_BLUESCREEN      9
90 #define WID_VERB            10
91 #define WID_DIMCOLOR        11
92 #define WID_DIMHIDE         12
93 #define WID_DIMPREV         13
94 #define WID_PRESORDER       14
95 #define WID_STYLE           15
96 #define WID_ANIMPATH        16
97 #define WID_IMAGEMAP        17
98 #define WID_ISANIMATION     18
99 #define WID_THAT_NEED_ANIMINFO 19
100 
101 #define WID_ISEMPTYPRESOBJ  20
102 #define WID_ISPRESOBJ       21
103 #define WID_MASTERDEPEND    22
104 
105 #define WID_NAVORDER        23
106 #define WID_PLACEHOLDERTEXT 24
107 #define WID_LEGACYFRAGMENT  25
108 
109 #define IMPRESS_MAP_ENTRIES \
110         { u"" UNO_NAME_OBJ_LEGACYFRAGMENT,WID_LEGACYFRAGMENT,  cppu::UnoType<drawing::XShape>::get(),                 0, 0},\
111         { u"" UNO_NAME_OBJ_ANIMATIONPATH, WID_ANIMPATH,        cppu::UnoType<drawing::XShape>::get(),                 0, 0},\
112         { u"" UNO_NAME_OBJ_BOOKMARK,      WID_BOOKMARK,        cppu::UnoType<OUString>::get(),                        0, 0},\
113         { u"" UNO_NAME_OBJ_DIMCOLOR,      WID_DIMCOLOR,        cppu::UnoType<sal_Int32>::get(),                       0, 0},\
114         { u"" UNO_NAME_OBJ_DIMHIDE,       WID_DIMHIDE,         cppu::UnoType<bool>::get(),                            0, 0},\
115         { u"" UNO_NAME_OBJ_DIMPREV,       WID_DIMPREV,         cppu::UnoType<bool>::get(),                            0, 0},\
116         { u"" UNO_NAME_OBJ_EFFECT,        WID_EFFECT,          cppu::UnoType<presentation::AnimationEffect>::get(),   0, 0},\
117         { u"" UNO_NAME_OBJ_ISEMPTYPRESOBJ,WID_ISEMPTYPRESOBJ,  cppu::UnoType<bool>::get(),                            0, 0},\
118         { u"" UNO_NAME_OBJ_ISPRESOBJ,     WID_ISPRESOBJ,       cppu::UnoType<bool>::get(),                            css::beans::PropertyAttribute::READONLY, 0},\
119         { u"" UNO_NAME_OBJ_MASTERDEPENDENT,WID_MASTERDEPEND,   cppu::UnoType<bool>::get(),                            0, 0},\
120         { u"" UNO_NAME_OBJ_CLICKACTION,   WID_CLICKACTION,     cppu::UnoType<presentation::ClickAction>::get(),       0, 0},\
121         { u"" UNO_NAME_OBJ_PLAYFULL,      WID_PLAYFULL,        cppu::UnoType<bool>::get(),                            0, 0},\
122         { u"" UNO_NAME_OBJ_PRESORDER,     WID_PRESORDER,       cppu::UnoType<sal_Int32>::get(),                       0, 0},\
123         { u"" UNO_NAME_OBJ_STYLE,         WID_STYLE,           cppu::UnoType<style::XStyle>::get(),                   css::beans::PropertyAttribute::MAYBEVOID, 0},\
124         { u"" UNO_NAME_OBJ_SOUNDFILE,     WID_SOUNDFILE,       cppu::UnoType<OUString>::get(),                        0, 0},\
125         { u"" UNO_NAME_OBJ_SOUNDON,       WID_SOUNDON,         cppu::UnoType<bool>::get(),                            0, 0},\
126         { u"" UNO_NAME_OBJ_SPEED,         WID_SPEED,           cppu::UnoType<presentation::AnimationSpeed>::get(),    0, 0},\
127         { u"" UNO_NAME_OBJ_TEXTEFFECT,    WID_TEXTEFFECT,      cppu::UnoType<presentation::AnimationEffect>::get(),   0, 0},\
128         { u"" UNO_NAME_OBJ_BLUESCREEN,    WID_BLUESCREEN,      cppu::UnoType<sal_Int32>::get(),                       0, 0},\
129         { u"" UNO_NAME_OBJ_VERB,          WID_VERB,            cppu::UnoType<sal_Int32>::get(),                       0, 0},\
130         { u"IsAnimation",              WID_ISANIMATION,     cppu::UnoType<bool>::get(),                            0, 0},\
131         { u"NavigationOrder",          WID_NAVORDER,        cppu::UnoType<sal_Int32>::get(),                       0, 0},\
132         { u"PlaceholderText",          WID_PLACEHOLDERTEXT, cppu::UnoType<OUString>::get(),                        0, 0},\
133         { u"", 0, css::uno::Type(), 0, 0 }
134 
lcl_GetImpress_SdXShapePropertyGraphicMap_Impl()135     static const SfxItemPropertyMapEntry* lcl_GetImpress_SdXShapePropertyGraphicMap_Impl()
136     {
137 
138         static const SfxItemPropertyMapEntry aImpress_SdXShapePropertyGraphicMap_Impl[] =
139         {
140             { u"ImageMap",             WID_IMAGEMAP,        cppu::UnoType<container::XIndexContainer>::get(),    0, 0 },
141             IMPRESS_MAP_ENTRIES
142         };
143         return aImpress_SdXShapePropertyGraphicMap_Impl;
144     }
145 
lcl_GetImpress_SdXShapePropertySimpleMap_Impl()146     static const SfxItemPropertyMapEntry* lcl_GetImpress_SdXShapePropertySimpleMap_Impl()
147     {
148 
149         static const SfxItemPropertyMapEntry aImpress_SdXShapePropertySimpleMap_Impl[] =
150         {
151             IMPRESS_MAP_ENTRIES
152         };
153         return aImpress_SdXShapePropertySimpleMap_Impl;
154     }
155 
156     #define DRAW_MAP_ENTRIES\
157         { u"" UNO_NAME_OBJ_BOOKMARK,      WID_BOOKMARK,       cppu::UnoType<OUString>::get(),                 0, 0},\
158         { u"" UNO_NAME_OBJ_CLICKACTION,   WID_CLICKACTION,    cppu::UnoType<presentation::ClickAction>::get(),0, 0},\
159         { u"" UNO_NAME_OBJ_STYLE,         WID_STYLE,          cppu::UnoType<style::XStyle>::get(),            css::beans::PropertyAttribute::MAYBEVOID, 0},\
160         { u"NavigationOrder",          WID_NAVORDER,       cppu::UnoType<sal_Int32>::get(),                0, 0},\
161         { u"", 0, css::uno::Type(), 0, 0 }
162 
lcl_GetDraw_SdXShapePropertySimpleMap_Impl()163     static const SfxItemPropertyMapEntry* lcl_GetDraw_SdXShapePropertySimpleMap_Impl()
164     {
165         static const SfxItemPropertyMapEntry aDraw_SdXShapePropertyMap_Impl[] =
166         {
167             DRAW_MAP_ENTRIES
168         };
169         return aDraw_SdXShapePropertyMap_Impl;
170     }
lcl_GetDraw_SdXShapePropertyGraphicMap_Impl()171     static const SfxItemPropertyMapEntry* lcl_GetDraw_SdXShapePropertyGraphicMap_Impl()
172     {
173         static const SfxItemPropertyMapEntry aDraw_SdXShapePropertyGraphicMap_Impl[] =
174         {
175             { u"ImageMap",             WID_IMAGEMAP,        cppu::UnoType<container::XIndexContainer>::get(),    0, 0 },
176             DRAW_MAP_ENTRIES
177         };
178         return aDraw_SdXShapePropertyGraphicMap_Impl;
179     }
lcl_ImplGetShapePropertyMap(bool bImpress,bool bGraphicObj)180     static const SfxItemPropertyMapEntry* lcl_ImplGetShapePropertyMap( bool bImpress, bool bGraphicObj )
181     {
182         const SfxItemPropertyMapEntry* pRet = nullptr;
183         if( bImpress )
184         {
185             if( bGraphicObj )
186                 pRet = lcl_GetImpress_SdXShapePropertyGraphicMap_Impl();
187             else
188                 pRet = lcl_GetImpress_SdXShapePropertySimpleMap_Impl();
189         }
190         else
191         {
192             if( bGraphicObj )
193                 pRet = lcl_GetDraw_SdXShapePropertyGraphicMap_Impl();
194             else
195                 pRet = lcl_GetDraw_SdXShapePropertySimpleMap_Impl();
196         }
197         return pRet;
198 
199     }
lcl_ImplGetShapePropertySet(bool bImpress,bool bGraphicObj)200     static const SvxItemPropertySet* lcl_ImplGetShapePropertySet( bool bImpress, bool bGraphicObj )
201     {
202         const SvxItemPropertySet* pRet = nullptr;
203         if( bImpress )
204         {
205             if( bGraphicObj )
206             {
207                 static SvxItemPropertySet aImpress_SdXShapePropertyGraphicSet_Impl( lcl_GetImpress_SdXShapePropertyGraphicMap_Impl(), SdrObject::GetGlobalDrawObjectItemPool());
208                 pRet = &aImpress_SdXShapePropertyGraphicSet_Impl;
209             }
210             else
211             {
212                 static SvxItemPropertySet aImpress_SdXShapePropertySet_Impl(lcl_GetImpress_SdXShapePropertySimpleMap_Impl(), SdrObject::GetGlobalDrawObjectItemPool());
213                 pRet = &aImpress_SdXShapePropertySet_Impl;
214             }
215         }
216         else
217         {
218             if( bGraphicObj )
219             {
220                 static SvxItemPropertySet aDraw_SdXShapePropertyGraphicSet_Impl(lcl_GetDraw_SdXShapePropertyGraphicMap_Impl(), SdrObject::GetGlobalDrawObjectItemPool());
221                 pRet = &aDraw_SdXShapePropertyGraphicSet_Impl;
222             }
223             else
224             {
225                 static SvxItemPropertySet aDraw_SdXShapePropertySet_Impl( lcl_GetDraw_SdXShapePropertySimpleMap_Impl(), SdrObject::GetGlobalDrawObjectItemPool());
226                 pRet = &aDraw_SdXShapePropertySet_Impl;
227             }
228         }
229         return pRet;
230     }
lcl_GetEmpty_SdXShapePropertyMap_Impl()231     static const SfxItemPropertyMapEntry* lcl_GetEmpty_SdXShapePropertyMap_Impl()
232     {
233         static const SfxItemPropertyMapEntry aEmpty_SdXShapePropertyMap_Impl[] =
234         {
235             { u"", 0, css::uno::Type(), 0, 0 }
236         };
237         return aEmpty_SdXShapePropertyMap_Impl;
238     }
239 
lcl_GetEmpty_SdXShapePropertySet_Impl()240     static const SvxItemPropertySet* lcl_GetEmpty_SdXShapePropertySet_Impl()
241     {
242         static SvxItemPropertySet aEmptyPropSet( lcl_GetEmpty_SdXShapePropertyMap_Impl(), SdrObject::GetGlobalDrawObjectItemPool() );
243         return &aEmptyPropSet;
244     }
ImplGetSupportedMacroItems()245 const SvEventDescription* ImplGetSupportedMacroItems()
246 {
247     static const SvEventDescription aMacroDescriptionsImpl[] =
248     {
249         { SvMacroItemId::OnMouseOver, "OnMouseOver" },
250         { SvMacroItemId::OnMouseOut,  "OnMouseOut" },
251         { SvMacroItemId::NONE, nullptr }
252     };
253 
254     return aMacroDescriptionsImpl;
255 }
256 
SdXShape(SvxShape * pShape,SdXImpressDocument * pModel)257 SdXShape::SdXShape(SvxShape* pShape, SdXImpressDocument* pModel)
258 :   mpShape( pShape ),
259     mpPropSet( pModel?
260                     lcl_ImplGetShapePropertySet(pModel->IsImpressDocument(), pShape->getShapeKind() == OBJ_GRAF )
261                 :   lcl_GetEmpty_SdXShapePropertySet_Impl() ),
262     mpMap( pModel?
263                     lcl_ImplGetShapePropertyMap(pModel->IsImpressDocument(), pShape->getShapeKind() == OBJ_GRAF )
264                 :   lcl_GetEmpty_SdXShapePropertyMap_Impl() ),
265     mpModel(pModel)
266 {
267 
268     pShape->setMaster( this );
269 }
270 
~SdXShape()271 SdXShape::~SdXShape() noexcept
272 {
273 }
274 
dispose()275 void SdXShape::dispose()
276 {
277     mpShape->setMaster( nullptr );
278     delete this;
279 }
280 
queryInterface(const uno::Type & rType)281 uno::Any SAL_CALL SdXShape::queryInterface( const uno::Type & rType )
282 {
283     return mpShape->queryInterface( rType );
284 }
285 
acquire()286 void SAL_CALL SdXShape::acquire() noexcept
287 {
288     mpShape->acquire();
289 }
290 
release()291 void SAL_CALL SdXShape::release() noexcept
292 {
293     mpShape->release();
294 }
295 
queryAggregation(const css::uno::Type & rType,css::uno::Any & aAny)296 bool SdXShape::queryAggregation( const css::uno::Type & rType, css::uno::Any& aAny )
297 {
298     if( mpModel && mpModel ->IsImpressDocument() )
299     {
300         if( rType == cppu::UnoType<document::XEventsSupplier>::get())
301         {
302             aAny <<= uno::Reference< document::XEventsSupplier >(this);
303             return true;
304         }
305     }
306 
307     return false;
308 }
309 
getTypes()310 uno::Sequence< uno::Type > SAL_CALL SdXShape::getTypes()
311 {
312     if( mpModel && !mpModel->IsImpressDocument() )
313     {
314         return mpShape->_getTypes();
315     }
316     else
317     {
318         sal_uInt32 nObjId = mpShape->getShapeKind();
319         uno::Sequence< uno::Type > aTypes;
320         SdTypesCache& gImplTypesCache = SD_MOD()->gImplTypesCache;
321         SdTypesCache::iterator aIter( gImplTypesCache.find( nObjId ) );
322         if( aIter == gImplTypesCache.end() )
323         {
324             aTypes = mpShape->_getTypes();
325             sal_uInt32 nCount = aTypes.getLength();
326             aTypes.realloc( nCount+1 );
327             aTypes[nCount] = cppu::UnoType<lang::XTypeProvider>::get();
328 
329             gImplTypesCache.insert(std::make_pair(nObjId, aTypes));
330         }
331         else
332         {
333             // use the already computed implementation id
334             aTypes = (*aIter).second;
335         }
336         return aTypes;
337     }
338 }
339 
340 // XPropertyState
getPropertyState(const OUString & PropertyName)341 beans::PropertyState SAL_CALL SdXShape::getPropertyState( const OUString& PropertyName )
342 {
343     SolarMutexGuard aGuard;
344 
345     if( mpPropSet->getPropertyMapEntry(PropertyName) )
346     {
347         return beans::PropertyState_DIRECT_VALUE;
348     }
349     else
350     {
351         SdrObject* pObj = mpShape->GetSdrObject();
352         if( pObj == nullptr || ( pObj->getSdrPageFromSdrObject()->IsMasterPage() && pObj->IsEmptyPresObj() ) )
353             return beans::PropertyState_DEFAULT_VALUE;
354 
355         return mpShape->_getPropertyState( PropertyName );
356     }
357 }
358 
setPropertyToDefault(const OUString & PropertyName)359 void SAL_CALL SdXShape::setPropertyToDefault( const OUString& PropertyName )
360 {
361     SolarMutexGuard aGuard;
362 
363     if( mpPropSet->getPropertyMapEntry(PropertyName) )
364     {
365         return;
366     }
367     else
368     {
369         mpShape->_setPropertyToDefault(PropertyName);
370     }
371 }
372 
getPropertyDefault(const OUString & aPropertyName)373 uno::Any SAL_CALL SdXShape::getPropertyDefault( const OUString& aPropertyName )
374 {
375     SolarMutexGuard aGuard;
376 
377     if( mpPropSet->getPropertyMapEntry(aPropertyName) )
378     {
379         return getPropertyValue( aPropertyName );
380     }
381     else
382     {
383         uno::Any aRet( mpShape->_getPropertyDefault(aPropertyName) );
384         return aRet;
385     }
386 }
387 
388 //XPropertySet
getPropertySetInfo()389 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL SdXShape::getPropertySetInfo()
390 {
391     SfxItemPropertyMapEntry const * nObjId = mpShape->getPropertyMapEntries();
392     css::uno::Reference<css::beans::XPropertySetInfo> pInfo;
393 
394     SdExtPropertySetInfoCache& rCache = (mpModel && mpModel->IsImpressDocument()) ?
395         SD_MOD()->gImplImpressPropertySetInfoCache : SD_MOD()->gImplDrawPropertySetInfoCache;
396 
397     SdExtPropertySetInfoCache::iterator aIter( rCache.find( nObjId ) );
398     if( aIter == rCache.end() )
399     {
400         uno::Reference< beans::XPropertySetInfo > xInfo( mpShape->_getPropertySetInfo() );
401         pInfo = new SfxExtItemPropertySetInfo( mpMap, xInfo->getProperties() );
402 
403         rCache.insert(std::make_pair(nObjId, pInfo));
404     }
405     else
406     {
407         // use the already computed implementation id
408         pInfo = (*aIter).second;
409     }
410 
411     return pInfo;
412 }
413 
setPropertyValue(const OUString & aPropertyName,const css::uno::Any & aValue)414 void SAL_CALL SdXShape::setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue )
415 {
416     SolarMutexGuard aGuard;
417 
418     const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
419 
420     if( pEntry )
421     {
422         SdrObject* pObj = mpShape->GetSdrObject();
423         if( pObj )
424         {
425             SdAnimationInfo* pInfo = GetAnimationInfo(pEntry->nWID <= WID_THAT_NEED_ANIMINFO);
426 
427             switch(pEntry->nWID)
428             {
429                 case WID_NAVORDER:
430                 {
431                     sal_Int32 nNavOrder = 0;
432                     if(!(aValue >>= nNavOrder))
433                         throw lang::IllegalArgumentException();
434 
435                     SdrObjList* pObjList = pObj->getParentSdrObjListFromSdrObject();
436                     if( pObjList )
437                         pObjList->SetObjectNavigationPosition( *pObj, (nNavOrder < 0) ? SAL_MAX_UINT32 : static_cast< sal_uInt32 >( nNavOrder ) );
438                     break;
439                 }
440 
441                 case WID_EFFECT:
442                 {
443                     AnimationEffect eEffect;
444                     if(!(aValue >>= eEffect))
445                         throw lang::IllegalArgumentException();
446 
447                     EffectMigration::SetAnimationEffect( mpShape, eEffect );
448                     break;
449                 }
450                 case WID_TEXTEFFECT:
451                 {
452                     AnimationEffect eEffect;
453                     if(!(aValue >>= eEffect))
454                         throw lang::IllegalArgumentException();
455 
456                     EffectMigration::SetTextAnimationEffect( mpShape, eEffect );
457                     break;
458                 }
459                 case WID_SPEED:
460                 {
461                     AnimationSpeed eSpeed;
462                     if(!(aValue>>=eSpeed))
463                         throw lang::IllegalArgumentException();
464 
465                     EffectMigration::SetAnimationSpeed( mpShape, eSpeed );
466                     break;
467                 }
468                 case WID_ISANIMATION:
469                 {
470                     bool bIsAnimation(false);
471 
472                     if(!(aValue >>= bIsAnimation))
473                     {
474                         throw lang::IllegalArgumentException();
475                     }
476 
477                     if(bIsAnimation)
478                     {
479                         SdrObjGroup* pGroup = dynamic_cast< SdrObjGroup* >(pObj);
480                         SdPage* pPage = pGroup ? dynamic_cast< SdPage* >(pGroup->getSdrPageFromSdrObject()) : nullptr;
481 
482                         if (pPage)
483                         {
484                             // #i42894# Animated Group object, migrate that effect
485                             EffectMigration::CreateAnimatedGroup(*pGroup, *pPage);
486 
487                             // #i42894# unfortunately when doing this all group members have to
488                             // be moved to the page as direct members, else the currently
489                             // available forms of animation do not work. If it succeeds,
490                             // the group is empty and can be removed and deleted
491                             if(!pGroup->GetSubList()->GetObjCount())
492                             {
493                                 pPage->NbcRemoveObject(pGroup->GetOrdNum());
494 
495                                 // always use SdrObject::Free(...) for SdrObjects (!)
496                                 SdrObject* pTemp(pGroup);
497                                 SdrObject::Free(pTemp);
498                             }
499                         }
500                     }
501                     //pInfo->mbIsMovie = bIsAnimation;
502                     break;
503                 }
504                 case WID_BOOKMARK:
505                 {
506                     OUString aString;
507                     if(!(aValue >>= aString))
508                         throw lang::IllegalArgumentException();
509 
510                     pInfo->SetBookmark( SdDrawPage::getUiNameFromPageApiName( aString ) );
511                     break;
512                 }
513                 case WID_CLICKACTION:
514                     ::cppu::any2enum< presentation::ClickAction >( pInfo->meClickAction, aValue);
515                     break;
516 
517 // TODO: WID_PLAYFULL:
518                 case WID_SOUNDFILE:
519                 {
520                     OUString aString;
521                     if(!(aValue >>= aString))
522                         throw lang::IllegalArgumentException();
523                     pInfo->maSoundFile = aString;
524                     EffectMigration::UpdateSoundEffect( mpShape, pInfo );
525                     break;
526                 }
527 
528                 case WID_SOUNDON:
529                 {
530                     if( !(aValue >>= pInfo->mbSoundOn) )
531                         throw lang::IllegalArgumentException();
532                     EffectMigration::UpdateSoundEffect( mpShape, pInfo );
533                     break;
534                 }
535                 case WID_VERB:
536                 {
537                     sal_Int32 nVerb = 0;
538                     if(!(aValue >>= nVerb))
539                         throw lang::IllegalArgumentException();
540 
541                     pInfo->mnVerb = static_cast<sal_uInt16>(nVerb);
542                     break;
543                 }
544                 case WID_DIMCOLOR:
545                 {
546                     sal_Int32 nColor = 0;
547 
548                     if( !(aValue >>= nColor) )
549                         throw lang::IllegalArgumentException();
550 
551                     EffectMigration::SetDimColor( mpShape, nColor );
552                     break;
553                 }
554                 case WID_DIMHIDE:
555                 {
556                     bool bDimHide = false;
557                     if( !(aValue >>= bDimHide) )
558                         throw lang::IllegalArgumentException();
559 
560                     EffectMigration::SetDimHide( mpShape, bDimHide );
561                     break;
562                 }
563                 case WID_DIMPREV:
564                 {
565                     bool bDimPrevious = false;
566                     if( !(aValue >>= bDimPrevious) )
567                         throw lang::IllegalArgumentException();
568 
569                     EffectMigration::SetDimPrevious( mpShape, bDimPrevious );
570                     break;
571                 }
572                 case WID_PRESORDER:
573                 {
574                     sal_Int32 nNewPos = 0;
575                     if( !(aValue >>= nNewPos) )
576                         throw lang::IllegalArgumentException();
577 
578                     EffectMigration::SetPresentationOrder( mpShape, nNewPos );
579                     break;
580                 }
581                 case WID_STYLE:
582                     SetStyleSheet( aValue );
583                     break;
584                 case WID_ISEMPTYPRESOBJ:
585                     SetEmptyPresObj( ::cppu::any2bool(aValue) );
586                     break;
587                 case WID_MASTERDEPEND:
588                     SetMasterDepend( ::cppu::any2bool(aValue) );
589                     break;
590 
591                 case WID_LEGACYFRAGMENT:
592                     {
593                         uno::Reference< io::XInputStream > xInputStream;
594                         aValue >>= xInputStream;
595                         if( xInputStream.is() )
596                         {
597                             SvInputStream aStream( xInputStream );
598                             SdrObject* pObject = mpShape->GetSdrObject();
599                             SvxMSDffManager::ReadObjText( aStream, pObject );
600                         }
601                     }
602                     break;
603 
604                 case WID_ANIMPATH:
605                 {
606                     uno::Reference< drawing::XShape > xShape( aValue, uno::UNO_QUERY );
607                     SdrPathObj* pObj2 = xShape.is() ? dynamic_cast< SdrPathObj* >( GetSdrObjectFromXShape( xShape ) ) : nullptr;
608 
609                     if( pObj2 == nullptr )
610                         throw lang::IllegalArgumentException();
611 
612                     EffectMigration::SetAnimationPath( mpShape, pObj2 );
613                     break;
614                 }
615                 case WID_IMAGEMAP:
616                 {
617                     SdDrawDocument* pDoc = mpModel?mpModel->GetDoc():nullptr;
618                     if( pDoc )
619                     {
620                         ImageMap aImageMap;
621                         uno::Reference< uno::XInterface > xImageMap;
622                         aValue >>= xImageMap;
623 
624                         if( !xImageMap.is() || !SvUnoImageMap_fillImageMap( xImageMap, aImageMap ) )
625                             throw lang::IllegalArgumentException();
626 
627                         SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo(pObj);
628                         if( pIMapInfo )
629                         {
630                             // replace existing image map
631                             pIMapInfo->SetImageMap( aImageMap );
632                         }
633                         else
634                         {
635                             // insert new user data with image map
636                             pObj->AppendUserData(std::unique_ptr<SdrObjUserData>(new SvxIMapInfo(aImageMap) ));
637                         }
638                     }
639                 }
640                 break;
641             }
642         }
643     }
644     else
645     {
646         mpShape->_setPropertyValue(aPropertyName, aValue);
647     }
648 
649     if( mpModel )
650         mpModel->SetModified();
651 }
652 
getPropertyValue(const OUString & PropertyName)653 css::uno::Any SAL_CALL SdXShape::getPropertyValue( const OUString& PropertyName )
654 {
655     SolarMutexGuard aGuard;
656 
657     uno::Any aRet;
658 
659     const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName);
660 
661     if( pEntry && mpShape->GetSdrObject() )
662     {
663         SdAnimationInfo* pInfo = GetAnimationInfo();
664 
665         switch(pEntry->nWID)
666         {
667         case WID_NAVORDER:
668             {
669                 const sal_uInt32 nNavOrder = mpShape->GetSdrObject()->GetNavigationPosition();
670                 aRet <<= nNavOrder == SAL_MAX_UINT32 ? static_cast<sal_Int32>(-1) : static_cast< sal_Int32 >(nNavOrder);
671             }
672             break;
673         case WID_EFFECT:
674             aRet <<= EffectMigration::GetAnimationEffect( mpShape );
675             break;
676         case WID_TEXTEFFECT:
677             aRet <<= EffectMigration::GetTextAnimationEffect( mpShape );
678             break;
679         case WID_ISPRESOBJ:
680             aRet <<= IsPresObj();
681             break;
682         case WID_ISEMPTYPRESOBJ:
683             aRet <<= IsEmptyPresObj();
684             break;
685         case WID_MASTERDEPEND:
686             aRet <<= IsMasterDepend();
687             break;
688         case WID_SPEED:
689             aRet <<= EffectMigration::GetAnimationSpeed( mpShape );
690             break;
691         case WID_ISANIMATION:
692             aRet <<= (pInfo && pInfo->mbIsMovie);
693             break;
694         case WID_PLACEHOLDERTEXT:
695             aRet <<= GetPlaceholderText();
696             break;
697         case WID_BOOKMARK:
698         {
699             OUString aString;
700             SdDrawDocument* pDoc = mpModel ? mpModel->GetDoc() : nullptr;
701             if (pInfo && pDoc)
702             {
703                 // is the bookmark a page?
704                 bool bIsMasterPage;
705                 if(pDoc->GetPageByName( pInfo->GetBookmark(), bIsMasterPage ) != SDRPAGE_NOTFOUND)
706                 {
707                     aString = SdDrawPage::getPageApiNameFromUiName( pInfo->GetBookmark() );
708                 }
709                 else
710                 {
711                     aString = pInfo->GetBookmark() ;
712                     sal_Int32 nPos = aString.lastIndexOf( '#' );
713                     if( nPos >= 0 )
714                     {
715                         OUString aURL( aString.copy( 0, nPos+1 ) );
716                         OUString aName( aString.copy( nPos+1 ) );
717                         if(pDoc->GetPageByName( aName, bIsMasterPage ) != SDRPAGE_NOTFOUND)
718                         {
719                             aURL += SdDrawPage::getPageApiNameFromUiName( aName );
720                             aString = aURL;
721                         }
722                     }
723                 }
724             }
725 
726             aRet <<= aString;
727             break;
728         }
729         case WID_CLICKACTION:
730             aRet <<= ( pInfo?pInfo->meClickAction:presentation::ClickAction_NONE );
731             break;
732         case WID_PLAYFULL:
733             aRet <<= ( pInfo && pInfo->mbPlayFull );
734             break;
735         case WID_SOUNDFILE:
736             aRet <<= EffectMigration::GetSoundFile( mpShape );
737             break;
738         case WID_SOUNDON:
739             aRet <<= EffectMigration::GetSoundOn( mpShape );
740             break;
741         case WID_BLUESCREEN:
742             aRet <<= pInfo ? pInfo->maBlueScreen : Color(0x00ffffff);
743             break;
744         case WID_VERB:
745             aRet <<= static_cast<sal_Int32>( pInfo?pInfo->mnVerb:0 );
746             break;
747         case WID_DIMCOLOR:
748             aRet <<= EffectMigration::GetDimColor( mpShape );
749             break;
750         case WID_DIMHIDE:
751             aRet <<= EffectMigration::GetDimHide( mpShape );
752             break;
753         case WID_DIMPREV:
754             aRet <<= EffectMigration::GetDimPrevious( mpShape );
755             break;
756         case WID_PRESORDER:
757             aRet <<= EffectMigration::GetPresentationOrder( mpShape );
758             break;
759         case WID_STYLE:
760             aRet = GetStyleSheet();
761             break;
762         case WID_IMAGEMAP:
763             {
764                 uno::Reference< uno::XInterface > xImageMap;
765 
766                 SdDrawDocument* pDoc = mpModel?mpModel->GetDoc():nullptr;
767                 if( pDoc )
768                 {
769 
770                     SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo(mpShape->GetSdrObject());
771                     if( pIMapInfo )
772                     {
773                         const ImageMap& rIMap = pIMapInfo->GetImageMap();
774                         xImageMap = SvUnoImageMap_createInstance( rIMap, ImplGetSupportedMacroItems() );
775                     }
776                     else
777                     {
778                         xImageMap = SvUnoImageMap_createInstance();
779                     }
780                 }
781 
782                 aRet <<= uno::Reference< container::XIndexContainer >::query( xImageMap );
783                 break;
784             }
785         }
786     }
787     else
788     {
789         aRet = mpShape->_getPropertyValue(PropertyName);
790     }
791 
792     return aRet;
793 }
794 
795 /** */
GetAnimationInfo(bool bCreate) const796 SdAnimationInfo* SdXShape::GetAnimationInfo( bool bCreate ) const
797 {
798     SdAnimationInfo* pInfo = nullptr;
799 
800     SdrObject* pObj = mpShape->GetSdrObject();
801     if(pObj)
802         pInfo = SdDrawDocument::GetShapeUserData(*pObj, bCreate);
803 
804     return pInfo;
805 }
806 
getSupportedServiceNames()807 uno::Sequence< OUString > SAL_CALL SdXShape::getSupportedServiceNames()
808 {
809     std::vector<std::u16string_view> aAdd{ u"com.sun.star.presentation.Shape",
810                                        u"com.sun.star.document.LinkTarget" };
811 
812     SdrObject* pObj = mpShape->GetSdrObject();
813     if(pObj && pObj->GetObjInventor() == SdrInventor::Default )
814     {
815         sal_uInt32 nInventor = pObj->GetObjIdentifier();
816         switch( nInventor )
817         {
818         case OBJ_TITLETEXT:
819             aAdd.emplace_back(u"com.sun.star.presentation.TitleTextShape");
820             break;
821         case OBJ_OUTLINETEXT:
822             aAdd.emplace_back(u"com.sun.star.presentation.OutlinerShape");
823             break;
824         }
825     }
826     return comphelper::concatSequences(mpShape->_getSupportedServiceNames(), aAdd);
827 }
828 
829 /** checks if this is a presentation object
830  */
IsPresObj() const831 bool SdXShape::IsPresObj() const
832 {
833     SdrObject* pObj = mpShape->GetSdrObject();
834     if(pObj)
835     {
836         SdPage* pPage = dynamic_cast<SdPage* >(pObj->getSdrPageFromSdrObject());
837         if(pPage)
838             return pPage->GetPresObjKind(pObj) != PresObjKind::NONE;
839     }
840     return false;
841 }
842 
843 /** checks if this presentation object is empty
844  */
IsEmptyPresObj() const845 bool SdXShape::IsEmptyPresObj() const
846 {
847     SdrObject* pObj = mpShape->GetSdrObject();
848     if( (pObj != nullptr) && pObj->IsEmptyPresObj() )
849     {
850         // check if the object is in edit, then if it's temporarily not empty
851         SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj );
852         if( pTextObj == nullptr )
853             return true;
854 
855         return !pTextObj->CanCreateEditOutlinerParaObject();
856     }
857 
858     return false;
859 }
860 
GetPlaceholderText() const861 OUString SdXShape::GetPlaceholderText() const
862 {
863     // only possible if this actually *is* a presentation object
864     if( !IsPresObj() )
865         return OUString();
866 
867     SdrObject* pObj = mpShape->GetSdrObject();
868     if( pObj == nullptr )
869         return OUString();
870 
871     SdPage* pPage = dynamic_cast< SdPage* >(pObj->getSdrPageFromSdrObject());
872     DBG_ASSERT( pPage, "no page?" );
873     if( pPage == nullptr )
874         return OUString();
875 
876     return pPage->GetPresObjText( pPage->GetPresObjKind(pObj) );
877 }
878 
879 /** sets/reset the empty status of a presentation object
880 */
SetEmptyPresObj(bool bEmpty)881 void SdXShape::SetEmptyPresObj(bool bEmpty)
882 {
883     // only possible if this actually *is* a presentation object
884     if( !IsPresObj() )
885         return;
886 
887     SdrObject* pObj = mpShape->GetSdrObject();
888     if( pObj == nullptr )
889         return;
890 
891     if( pObj->IsEmptyPresObj() == bEmpty )
892         return;
893 
894     if(!bEmpty)
895     {
896         OutlinerParaObject* pOutlinerParaObject = pObj->GetOutlinerParaObject();
897         const bool bVertical = pOutlinerParaObject && pOutlinerParaObject->IsVertical();
898 
899         // really delete SdrOutlinerObj at pObj
900         pObj->NbcSetOutlinerParaObject(nullptr);
901         if( bVertical )
902             if (auto pTextObj = dynamic_cast<SdrTextObj*>( pObj ) )
903                 pTextObj->SetVerticalWriting( true );
904 
905         SdrGrafObj* pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj  );
906         if( pGraphicObj )
907         {
908             Graphic aEmpty;
909             pGraphicObj->SetGraphic(aEmpty);
910         }
911         else
912         {
913             SdrOle2Obj* pOleObj = dynamic_cast< SdrOle2Obj* >( pObj );
914             if( pOleObj )
915             {
916                 pOleObj->ClearGraphic();
917             }
918         }
919     }
920     else
921     {
922         // now set an empty OutlinerParaObject at pObj without
923         // any content but with the style of the old OutlinerParaObjects
924         // first paragraph
925         do
926         {
927             SdDrawDocument* pDoc = mpModel?mpModel->GetDoc():nullptr;
928             DBG_ASSERT( pDoc, "no document?" );
929             if( pDoc == nullptr)
930                 break;
931 
932             SdOutliner* pOutliner = pDoc->GetInternalOutliner();
933             DBG_ASSERT( pOutliner, "no outliner?" );
934             if( pOutliner == nullptr )
935                 break;
936 
937             SdPage* pPage = dynamic_cast< SdPage* >(pObj->getSdrPageFromSdrObject());
938             DBG_ASSERT( pPage, "no page?" );
939             if( pPage == nullptr )
940                 break;
941 
942             OutlinerParaObject* pOutlinerParaObject = pObj->GetOutlinerParaObject();
943             pOutliner->SetText( *pOutlinerParaObject );
944             const bool bVertical = pOutliner->IsVertical();
945 
946             pOutliner->Clear();
947             pOutliner->SetVertical( bVertical );
948             pOutliner->SetStyleSheetPool( static_cast<SfxStyleSheetPool*>(pDoc->GetStyleSheetPool()) );
949             pOutliner->SetStyleSheet( 0, pPage->GetTextStyleSheetForObject( pObj ) );
950             pOutliner->Insert( pPage->GetPresObjText( pPage->GetPresObjKind(pObj) ) );
951             pObj->SetOutlinerParaObject( pOutliner->CreateParaObject() );
952             pOutliner->Clear();
953         }
954         while(false);
955     }
956 
957     pObj->SetEmptyPresObj(bEmpty);
958 }
959 
IsMasterDepend() const960 bool SdXShape::IsMasterDepend() const noexcept
961 {
962     SdrObject* pObj = mpShape->GetSdrObject();
963     return pObj && pObj->GetUserCall() != nullptr;
964 }
965 
SetMasterDepend(bool bDepend)966 void SdXShape::SetMasterDepend( bool bDepend ) noexcept
967 {
968     if( IsMasterDepend() == bDepend )
969         return;
970 
971     SdrObject* pObj = mpShape->GetSdrObject();
972     if( pObj )
973     {
974         if( bDepend )
975         {
976             SdPage* pPage = dynamic_cast< SdPage* >(pObj->getSdrPageFromSdrObject());
977             pObj->SetUserCall( pPage );
978         }
979         else
980         {
981             pObj->SetUserCall( nullptr );
982         }
983     }
984 }
985 
SetStyleSheet(const uno::Any & rAny)986 void SdXShape::SetStyleSheet( const uno::Any& rAny )
987 {
988     SdrObject* pObj = mpShape->GetSdrObject();
989     if( pObj == nullptr )
990         throw beans::UnknownPropertyException();
991 
992     uno::Reference< style::XStyle > xStyle( rAny, uno::UNO_QUERY );
993     SfxStyleSheet* pStyleSheet = SfxUnoStyleSheet::getUnoStyleSheet( xStyle );
994 
995     const SfxStyleSheet* pOldStyleSheet = pObj->GetStyleSheet();
996     if( pOldStyleSheet == pStyleSheet )
997         return;
998 
999     if( pStyleSheet == nullptr || (pStyleSheet->GetFamily() != SfxStyleFamily::Para && pStyleSheet->GetFamily() != SfxStyleFamily::Page) )
1000         throw lang::IllegalArgumentException();
1001 
1002     pObj->SetStyleSheet( pStyleSheet, false );
1003 
1004     SdDrawDocument* pDoc = mpModel? mpModel->GetDoc() : nullptr;
1005     if( pDoc )
1006     {
1007         ::sd::DrawDocShell* pDocSh = pDoc->GetDocSh();
1008         ::sd::ViewShell* pViewSh = pDocSh ? pDocSh->GetViewShell() : nullptr;
1009 
1010         if( pViewSh )
1011             pViewSh->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 );
1012     }
1013 }
1014 
GetStyleSheet() const1015 uno::Any SdXShape::GetStyleSheet() const
1016 {
1017     SdrObject* pObj = mpShape->GetSdrObject();
1018     if( pObj == nullptr )
1019         throw beans::UnknownPropertyException();
1020 
1021     SfxStyleSheet* pStyleSheet = pObj->GetStyleSheet();
1022     // it is possible for shapes inside a draw to have a presentation style
1023     // but we don't want this for the api
1024     if( (pStyleSheet == nullptr) || ((pStyleSheet->GetFamily() != SfxStyleFamily::Para) && !mpModel->IsImpressDocument()) )
1025         return Any();
1026 
1027     return Any( uno::Reference< style::XStyle >( dynamic_cast< SfxUnoStyleSheet* >( pStyleSheet ) ) );
1028 }
1029 
1030 class SdUnoEventsAccess : public cppu::WeakImplHelper< css::container::XNameReplace, css::lang::XServiceInfo >
1031 {
1032 private:
1033     SdXShape*   mpShape;
1034 
1035 public:
1036     explicit SdUnoEventsAccess(SdXShape* pShape) noexcept;
1037 
1038     // XNameReplace
1039     virtual void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override;
1040 
1041     // XNameAccess
1042     virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
1043     virtual css::uno::Sequence< OUString > SAL_CALL getElementNames(  ) override;
1044     virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
1045 
1046     // XElementAccess
1047     virtual css::uno::Type SAL_CALL getElementType(  ) override;
1048     virtual sal_Bool SAL_CALL hasElements(  ) override;
1049 
1050     // XServiceInfo
1051     virtual OUString SAL_CALL getImplementationName(  ) override;
1052     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
1053     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;
1054 };
1055 
1056 // XEventsSupplier
getEvents()1057 uno::Reference< container::XNameReplace > SAL_CALL SdXShape::getEvents(  )
1058 {
1059     return new SdUnoEventsAccess( this );
1060 }
1061 
1062 constexpr OUStringLiteral gaStrOnClick( u"OnClick" );
1063 constexpr OUStringLiteral gaStrServiceName( u"com.sun.star.documents.Events" );
1064 constexpr OUStringLiteral gaStrEventType( u"EventType" );
1065 constexpr OUStringLiteral gaStrPresentation( u"Presentation" );
1066 constexpr OUStringLiteral gaStrLibrary(u"Library");
1067 constexpr OUStringLiteral gaStrMacroName(u"MacroName");
1068 constexpr OUStringLiteral gaStrClickAction( u"ClickAction" );
1069 constexpr OUStringLiteral gaStrBookmark( u"Bookmark" );
1070 constexpr OUStringLiteral gaStrEffect( u"Effect" );
1071 constexpr OUStringLiteral gaStrPlayFull( u"PlayFull" );
1072 constexpr OUStringLiteral gaStrVerb( u"Verb" );
1073 constexpr OUStringLiteral gaStrSoundURL( u"SoundURL" );
1074 constexpr OUStringLiteral gaStrSpeed( u"Speed" );
1075 constexpr OUStringLiteral gaStrStarBasic( u"StarBasic" );
1076 constexpr OUStringLiteral gaStrScript( u"Script" );
1077 
SdUnoEventsAccess(SdXShape * pShape)1078 SdUnoEventsAccess::SdUnoEventsAccess( SdXShape* pShape ) noexcept
1079   : mpShape( pShape )
1080 {
1081 }
1082 
1083 namespace {
1084 
1085 enum class FoundFlags {
1086     NONE          = 0x0000,
1087     ClickAction   = 0x0001,
1088     Bookmark      = 0x0002,
1089     Effect        = 0x0004,
1090     PlayFull      = 0x0008,
1091     Verb          = 0x0010,
1092     SoundUrl      = 0x0020,
1093     Speed         = 0x0040,
1094     EventType     = 0x0080,
1095     Macro         = 0x0100,
1096     Library       = 0x0200,
1097 };
1098 
1099 }
1100 
1101 namespace o3tl {
1102     template<> struct typed_flags<FoundFlags> : is_typed_flags<FoundFlags, 0x03ff> {};
1103 }
1104 
clearEventsInAnimationInfo(SdAnimationInfo * pInfo)1105 static void clearEventsInAnimationInfo( SdAnimationInfo* pInfo )
1106 {
1107     pInfo->SetBookmark( "" );
1108     pInfo->mbSecondSoundOn = false;
1109     pInfo->mbSecondPlayFull = false;
1110     pInfo->meClickAction = presentation::ClickAction_NONE;
1111     pInfo->meSecondEffect = presentation::AnimationEffect_NONE;
1112     pInfo->meSecondSpeed = presentation::AnimationSpeed_MEDIUM;
1113     pInfo->mnVerb = 0;
1114 }
1115 
1116 // XNameReplace
replaceByName(const OUString & aName,const uno::Any & aElement)1117 void SAL_CALL SdUnoEventsAccess::replaceByName( const OUString& aName, const uno::Any& aElement )
1118 {
1119     if( mpShape == nullptr || aName != gaStrOnClick )
1120         throw container::NoSuchElementException();
1121 
1122     uno::Sequence< beans::PropertyValue > aProperties;
1123     if( !aElement.hasValue() || aElement.getValueType() != getElementType() || !(aElement >>= aProperties) )
1124         throw lang::IllegalArgumentException();
1125 
1126     FoundFlags nFound = FoundFlags::NONE;
1127 
1128     OUString aStrEventType;
1129     presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
1130     presentation::AnimationEffect eEffect = presentation::AnimationEffect_NONE;
1131     presentation::AnimationSpeed eSpeed = presentation::AnimationSpeed_MEDIUM;
1132     OUString aStrSoundURL;
1133     bool bPlayFull = false;
1134     sal_Int32 nVerb = 0;
1135     OUString aStrMacro;
1136     OUString aStrLibrary;
1137     OUString aStrBookmark;
1138 
1139     for( const beans::PropertyValue& rProperty : std::as_const(aProperties) )
1140     {
1141         if( !( nFound & FoundFlags::EventType ) && rProperty.Name == gaStrEventType )
1142         {
1143             if( rProperty.Value >>= aStrEventType )
1144             {
1145                 nFound |= FoundFlags::EventType;
1146                 continue;
1147             }
1148         }
1149         else if( !( nFound & FoundFlags::ClickAction ) && rProperty.Name == gaStrClickAction )
1150         {
1151             if( rProperty.Value >>= eClickAction )
1152             {
1153                 nFound |= FoundFlags::ClickAction;
1154                 continue;
1155             }
1156         }
1157         else if( !( nFound & FoundFlags::Macro ) && ( rProperty.Name == gaStrMacroName || rProperty.Name == gaStrScript ) )
1158         {
1159             if( rProperty.Value >>= aStrMacro )
1160             {
1161                 nFound |= FoundFlags::Macro;
1162                 continue;
1163             }
1164         }
1165         else if( !( nFound & FoundFlags::Library ) && rProperty.Name == gaStrLibrary )
1166         {
1167             if( rProperty.Value >>= aStrLibrary )
1168             {
1169                 nFound |= FoundFlags::Library;
1170                 continue;
1171             }
1172         }
1173         else if( !( nFound & FoundFlags::Effect ) && rProperty.Name == gaStrEffect )
1174         {
1175             if( rProperty.Value >>= eEffect )
1176             {
1177                 nFound |= FoundFlags::Effect;
1178                 continue;
1179             }
1180         }
1181         else if( !( nFound & FoundFlags::Bookmark ) && rProperty.Name == gaStrBookmark )
1182         {
1183             if( rProperty.Value >>= aStrBookmark )
1184             {
1185                 nFound |= FoundFlags::Bookmark;
1186                 continue;
1187             }
1188         }
1189         else if( !( nFound & FoundFlags::Speed ) && rProperty.Name == gaStrSpeed )
1190         {
1191             if( rProperty.Value >>= eSpeed )
1192             {
1193                 nFound |= FoundFlags::Speed;
1194                 continue;
1195             }
1196         }
1197         else if( !( nFound & FoundFlags::SoundUrl ) && rProperty.Name == gaStrSoundURL )
1198         {
1199             if( rProperty.Value >>= aStrSoundURL )
1200             {
1201                 nFound |= FoundFlags::SoundUrl;
1202                 continue;
1203             }
1204         }
1205         else if( !( nFound & FoundFlags::PlayFull ) && rProperty.Name == gaStrPlayFull )
1206         {
1207             if( rProperty.Value >>= bPlayFull )
1208             {
1209                 nFound |= FoundFlags::PlayFull;
1210                 continue;
1211             }
1212         }
1213         else if( !( nFound & FoundFlags::Verb ) && rProperty.Name == gaStrVerb )
1214         {
1215             if( rProperty.Value >>= nVerb )
1216             {
1217                 nFound |= FoundFlags::Verb;
1218                 continue;
1219             }
1220         }
1221 
1222         throw lang::IllegalArgumentException();
1223     }
1224 
1225     bool bOk = false;
1226     do
1227     {
1228         if( !( nFound & FoundFlags::EventType ) )
1229             break;
1230 
1231         if( aStrEventType == gaStrPresentation )
1232         {
1233             if( !( nFound & FoundFlags::ClickAction ) )
1234                 break;
1235 
1236             SdAnimationInfo* pInfo = mpShape->GetAnimationInfo();
1237             if( presentation::ClickAction_NONE == eClickAction && nullptr == pInfo )
1238             {
1239                 bOk = true;
1240                 break;
1241             }
1242 
1243             if( nullptr == pInfo )
1244                 pInfo = mpShape->GetAnimationInfo( true );
1245 
1246             DBG_ASSERT( pInfo, "shape animation info could not be created!" );
1247             if( nullptr == pInfo )
1248                 break;
1249 
1250             clearEventsInAnimationInfo( pInfo );
1251             pInfo->meClickAction = eClickAction;
1252 
1253             switch( eClickAction )
1254             {
1255             case presentation::ClickAction_NONE:
1256             case presentation::ClickAction_PREVPAGE:
1257             case presentation::ClickAction_NEXTPAGE:
1258             case presentation::ClickAction_FIRSTPAGE:
1259             case presentation::ClickAction_LASTPAGE:
1260             case presentation::ClickAction_INVISIBLE:
1261             case presentation::ClickAction_STOPPRESENTATION:
1262                 {
1263                     bOk = true;
1264                 }
1265                 break;
1266 
1267             case presentation::ClickAction_PROGRAM:
1268             case presentation::ClickAction_BOOKMARK:
1269             case presentation::ClickAction_DOCUMENT:
1270                 if( nFound & FoundFlags::Bookmark )
1271                 {
1272                     if( eClickAction == presentation::ClickAction_BOOKMARK )
1273                     {
1274                         aStrBookmark = getUiNameFromPageApiNameImpl( aStrBookmark );
1275                     }
1276                     else if( eClickAction == presentation::ClickAction_DOCUMENT )
1277                     {
1278                         sal_Int32 nPos = aStrBookmark.lastIndexOf( '#' );
1279                         if( nPos >= 0 )
1280                         {
1281                             OUString aURL( aStrBookmark.copy( 0, nPos+1 ) );
1282                             aURL += getUiNameFromPageApiNameImpl( aStrBookmark.copy( nPos+1 ) );
1283                             aStrBookmark = aURL;
1284                         }
1285                     }
1286 
1287                     pInfo->SetBookmark( aStrBookmark );
1288                     bOk = true;
1289                 }
1290                 break;
1291 
1292             case presentation::ClickAction_MACRO:
1293                 if( nFound & FoundFlags::Macro )
1294                 {
1295                     pInfo->SetBookmark( aStrMacro );
1296                     bOk = true;
1297                 }
1298                 break;
1299 
1300             case presentation::ClickAction_VERB:
1301                 if( nFound & FoundFlags::Verb )
1302                 {
1303                     pInfo->mnVerb = static_cast<sal_uInt16>(nVerb);
1304                     bOk = true;
1305                 }
1306                 break;
1307 
1308             case presentation::ClickAction_VANISH:
1309                 if( !( nFound & FoundFlags::Effect ) )
1310                     break;
1311 
1312                 pInfo->meSecondEffect = eEffect;
1313                 pInfo->meSecondSpeed = nFound & FoundFlags::Speed ? eSpeed : presentation::AnimationSpeed_MEDIUM;
1314 
1315                 bOk = true;
1316 
1317                 [[fallthrough]];
1318 
1319             case presentation::ClickAction_SOUND:
1320                 if( nFound & FoundFlags::SoundUrl )
1321                 {
1322                     pInfo->SetBookmark( aStrSoundURL );
1323                     if( eClickAction != presentation::ClickAction_SOUND )
1324                         pInfo->mbSecondSoundOn = !aStrSoundURL.isEmpty();
1325                     pInfo->mbSecondPlayFull = (nFound & FoundFlags::PlayFull) && bPlayFull;
1326 
1327                     bOk = true;
1328                 }
1329                 break;
1330             default:
1331                 break;
1332             }
1333         }
1334         else
1335         {
1336             SdAnimationInfo* pInfo = mpShape->GetAnimationInfo( true );
1337 
1338             DBG_ASSERT( pInfo, "shape animation info could not be created!" );
1339             if( nullptr == pInfo )
1340                 break;
1341 
1342             clearEventsInAnimationInfo( pInfo );
1343             pInfo->meClickAction = presentation::ClickAction_MACRO;
1344 
1345             if ( SfxApplication::IsXScriptURL( aStrMacro ) )
1346             {
1347                 pInfo->SetBookmark( aStrMacro );
1348             }
1349             else
1350             {
1351                 sal_Int32 nIdx{ 0 };
1352                 const OUString aLibName   = aStrMacro.getToken(0, '.', nIdx);
1353                 const OUString aModulName = aStrMacro.getToken(0, '.', nIdx);
1354                 const OUString aMacroName = aStrMacro.getToken(0, '.', nIdx);
1355 
1356                 OUStringBuffer sBuffer;
1357                 sBuffer.append( aMacroName );
1358                 sBuffer.append( '.' );
1359                 sBuffer.append( aModulName );
1360                 sBuffer.append( '.' );
1361                 sBuffer.append( aLibName );
1362                 sBuffer.append( '.' );
1363 
1364                 if ( aStrLibrary == "StarOffice" )
1365                 {
1366                     sBuffer.append( "BASIC" );
1367                 }
1368                 else
1369                 {
1370                     sBuffer.append( aStrLibrary );
1371                 }
1372 
1373                 pInfo->SetBookmark( sBuffer.makeStringAndClear() );
1374             }
1375             bOk = true;
1376         }
1377     }
1378     while(false);
1379 
1380     if( !bOk )
1381         throw lang::IllegalArgumentException();
1382 }
1383 
1384 // XNameAccess
getByName(const OUString & aName)1385 uno::Any SAL_CALL SdUnoEventsAccess::getByName( const OUString& aName )
1386 {
1387     if( mpShape == nullptr || aName != gaStrOnClick )
1388         throw container::NoSuchElementException();
1389 
1390     SdAnimationInfo* pInfo = mpShape->GetAnimationInfo();
1391 
1392     presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
1393     if( pInfo )
1394         eClickAction = pInfo->meClickAction;
1395 
1396     sal_Int32 nPropertyCount = 2;
1397     switch( eClickAction )
1398     {
1399     case presentation::ClickAction_NONE:
1400     case presentation::ClickAction_PREVPAGE:
1401     case presentation::ClickAction_NEXTPAGE:
1402     case presentation::ClickAction_FIRSTPAGE:
1403     case presentation::ClickAction_LASTPAGE:
1404     case presentation::ClickAction_INVISIBLE:
1405     case presentation::ClickAction_STOPPRESENTATION:
1406         break;
1407     case presentation::ClickAction_PROGRAM:
1408     case presentation::ClickAction_VERB:
1409     case presentation::ClickAction_BOOKMARK:
1410     case presentation::ClickAction_DOCUMENT:
1411     case presentation::ClickAction_MACRO:
1412         if ( !SfxApplication::IsXScriptURL( pInfo->GetBookmark() ) )
1413             nPropertyCount += 1;
1414         break;
1415 
1416     case presentation::ClickAction_SOUND:
1417         nPropertyCount += 2;
1418         break;
1419 
1420     case presentation::ClickAction_VANISH:
1421         nPropertyCount += 4;
1422         break;
1423     default:
1424         break;
1425     }
1426 
1427     uno::Sequence< beans::PropertyValue > aProperties( nPropertyCount );
1428     beans::PropertyValue* pProperties = aProperties.getArray();
1429 
1430     uno::Any aAny;
1431 
1432     if( eClickAction == presentation::ClickAction_MACRO )
1433     {
1434         if ( SfxApplication::IsXScriptURL( pInfo->GetBookmark() ) )
1435         {
1436             // Scripting Framework URL
1437             aAny <<= OUString(gaStrScript);
1438             pProperties->Name = gaStrEventType;
1439             pProperties->Handle = -1;
1440             pProperties->Value = aAny;
1441             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1442             pProperties++;
1443 
1444             aAny <<= pInfo->GetBookmark();
1445             pProperties->Name = gaStrScript;
1446             pProperties->Handle = -1;
1447             pProperties->Value = aAny;
1448             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1449             pProperties++;
1450         }
1451         else
1452         {
1453             // Old Basic macro URL
1454             aAny <<= OUString(gaStrStarBasic);
1455             pProperties->Name = gaStrEventType;
1456             pProperties->Handle = -1;
1457             pProperties->Value = aAny;
1458             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1459             pProperties++;
1460 
1461             OUString aMacro = pInfo->GetBookmark();
1462 
1463             // aMacro has got following format:
1464             // "Macroname.Modulname.Libname.Documentname" or
1465             // "Macroname.Modulname.Libname.Applicationname"
1466             sal_Int32 nIdx{ 0 };
1467             const OUString aMacroName = aMacro.getToken(0, '.', nIdx);
1468             const OUString aModulName = aMacro.getToken(0, '.', nIdx);
1469             const OUString aLibName   = aMacro.getToken(0, '.', nIdx);
1470 
1471             OUString sBuffer = aLibName +
1472                 "."  +
1473                 aModulName  +
1474                 "."  +
1475                 aMacroName;
1476 
1477             aAny <<= sBuffer;
1478             pProperties->Name = gaStrMacroName;
1479             pProperties->Handle = -1;
1480             pProperties->Value = aAny;
1481             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1482             pProperties++;
1483 
1484             aAny <<= OUString( "StarOffice" );
1485             pProperties->Name = gaStrLibrary;
1486             pProperties->Handle = -1;
1487             pProperties->Value = aAny;
1488             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1489         }
1490     }
1491     else
1492     {
1493         aAny <<= OUString(gaStrPresentation);
1494         pProperties->Name = gaStrEventType;
1495         pProperties->Handle = -1;
1496         pProperties->Value = aAny;
1497         pProperties->State = beans::PropertyState_DIRECT_VALUE;
1498         pProperties++;
1499 
1500         aAny <<= eClickAction;
1501         pProperties->Name = gaStrClickAction;
1502         pProperties->Handle = -1;
1503         pProperties->Value = aAny;
1504         pProperties->State = beans::PropertyState_DIRECT_VALUE;
1505         pProperties++;
1506 
1507         switch( eClickAction )
1508         {
1509         case presentation::ClickAction_NONE:
1510         case presentation::ClickAction_PREVPAGE:
1511         case presentation::ClickAction_NEXTPAGE:
1512         case presentation::ClickAction_FIRSTPAGE:
1513         case presentation::ClickAction_LASTPAGE:
1514         case presentation::ClickAction_INVISIBLE:
1515         case presentation::ClickAction_STOPPRESENTATION:
1516             break;
1517         case presentation::ClickAction_BOOKMARK:
1518             {
1519                 const OUString aStrBookmark( getPageApiNameFromUiName( pInfo->GetBookmark()) );
1520                 pProperties->Name = gaStrBookmark;
1521                 pProperties->Handle = -1;
1522                 pProperties->Value <<= aStrBookmark;
1523                 pProperties->State = beans::PropertyState_DIRECT_VALUE;
1524             }
1525             break;
1526 
1527         case presentation::ClickAction_DOCUMENT:
1528         case presentation::ClickAction_PROGRAM:
1529             {
1530                 OUString aString( pInfo->GetBookmark());
1531                 sal_Int32 nPos = aString.lastIndexOf( '#' );
1532                 if( nPos >= 0 )
1533                 {
1534                     OUString aURL( aString.copy( 0, nPos+1 ) );
1535                     aURL += getPageApiNameFromUiName( aString.copy( nPos+1 ) );
1536                     aString = aURL;
1537                 }
1538                 pProperties->Name = gaStrBookmark;
1539                 pProperties->Handle = -1;
1540                 pProperties->Value <<= aString;
1541                 pProperties->State = beans::PropertyState_DIRECT_VALUE;
1542             }
1543             break;
1544 
1545         case presentation::ClickAction_VANISH:
1546             aAny <<= pInfo->meSecondEffect;
1547             pProperties->Name = gaStrEffect;
1548             pProperties->Handle = -1;
1549             pProperties->Value = aAny;
1550             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1551             pProperties++;
1552 
1553             aAny <<= pInfo->meSecondSpeed;
1554             pProperties->Name = gaStrSpeed;
1555             pProperties->Handle = -1;
1556             pProperties->Value = aAny;
1557             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1558             pProperties++;
1559 
1560             [[fallthrough]];
1561 
1562         case presentation::ClickAction_SOUND:
1563             if( eClickAction == presentation::ClickAction_SOUND || pInfo->mbSecondSoundOn )
1564             {
1565                 aAny <<= pInfo->GetBookmark();
1566                 pProperties->Name = gaStrSoundURL;
1567                 pProperties->Handle = -1;
1568                 pProperties->Value = aAny;
1569                 pProperties->State = beans::PropertyState_DIRECT_VALUE;
1570                 pProperties++;
1571 
1572                 pProperties->Name = gaStrPlayFull;
1573                 pProperties->Handle = -1;
1574                 pProperties->Value <<= pInfo->mbSecondPlayFull;
1575                 pProperties->State = beans::PropertyState_DIRECT_VALUE;
1576             }
1577             break;
1578 
1579         case presentation::ClickAction_VERB:
1580             aAny <<= static_cast<sal_Int32>(pInfo->mnVerb);
1581             pProperties->Name = gaStrVerb;
1582             pProperties->Handle = -1;
1583             pProperties->Value = aAny;
1584             pProperties->State = beans::PropertyState_DIRECT_VALUE;
1585             break;
1586         default:
1587             break;
1588         }
1589     }
1590 
1591     aAny <<= aProperties;
1592     return aAny;
1593 }
1594 
getElementNames()1595 uno::Sequence< OUString > SAL_CALL SdUnoEventsAccess::getElementNames(  )
1596 {
1597     return { gaStrOnClick };
1598 }
1599 
hasByName(const OUString & aName)1600 sal_Bool SAL_CALL SdUnoEventsAccess::hasByName( const OUString& aName )
1601 {
1602     return aName == gaStrOnClick;
1603 }
1604 
1605 // XElementAccess
getElementType()1606 uno::Type SAL_CALL SdUnoEventsAccess::getElementType(  )
1607 {
1608     return cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get();
1609 }
1610 
hasElements()1611 sal_Bool SAL_CALL SdUnoEventsAccess::hasElements(  )
1612 {
1613     return true;
1614 }
1615 
1616 // XServiceInfo
getImplementationName()1617 OUString SAL_CALL SdUnoEventsAccess::getImplementationName(  )
1618 {
1619     return "SdUnoEventsAccess";
1620 }
1621 
supportsService(const OUString & ServiceName)1622 sal_Bool SAL_CALL SdUnoEventsAccess::supportsService( const OUString& ServiceName )
1623 {
1624     return cppu::supportsService(this, ServiceName);
1625 }
1626 
getSupportedServiceNames()1627 uno::Sequence< OUString > SAL_CALL SdUnoEventsAccess::getSupportedServiceNames(  )
1628 {
1629     return { gaStrServiceName };
1630 }
1631 
1632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1633