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