1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/document/XEventsSupplier.hpp>
21 #include <com/sun/star/container/XNameReplace.hpp>
22 #include <com/sun/star/presentation/AnimationSpeed.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <tools/urlobj.hxx>
25 #include <osl/diagnose.h>
26 #include <sal/log.hxx>
28 #include <sax/tools/converter.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnmspe.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xmloff/nmspmap.hxx>
35 #include "eventimp.hxx"
37 using namespace ::std
;
38 using namespace ::cppu
;
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::xml
;
41 using namespace ::com::sun::star::xml::sax
;
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::drawing
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::lang
;
46 using namespace ::com::sun::star::document
;
47 using namespace ::com::sun::star::container
;
48 using namespace ::com::sun::star::presentation
;
49 using namespace ::xmloff::token
;
51 SvXMLEnumMapEntry
<ClickAction
> const aXML_EventActions_EnumMap
[] =
53 { XML_NONE
, ClickAction_NONE
},
54 { XML_PREVIOUS_PAGE
, ClickAction_PREVPAGE
},
55 { XML_NEXT_PAGE
, ClickAction_NEXTPAGE
},
56 { XML_FIRST_PAGE
, ClickAction_FIRSTPAGE
},
57 { XML_LAST_PAGE
, ClickAction_LASTPAGE
},
58 { XML_HIDE
, ClickAction_INVISIBLE
},
59 { XML_STOP
, ClickAction_STOPPRESENTATION
},
60 { XML_EXECUTE
, ClickAction_PROGRAM
},
61 { XML_SHOW
, ClickAction_BOOKMARK
},
62 { XML_SHOW
, ClickAction_DOCUMENT
},
63 { XML_EXECUTE_MACRO
, ClickAction_MACRO
},
64 { XML_VERB
, ClickAction_VERB
},
65 { XML_FADE_OUT
, ClickAction_VANISH
},
66 { XML_SOUND
, ClickAction_SOUND
},
67 { XML_TOKEN_INVALID
, ClickAction(0) }
70 SdXMLEventContextData::SdXMLEventContextData(const Reference
< XShape
>& rxShape
)
71 : mxShape(rxShape
), mbValid(false), mbScript(false)
72 , meClickAction(ClickAction_NONE
), meEffect(EK_none
)
73 , meDirection(ED_none
), mnStartScale(100), meSpeed(AnimationSpeed_MEDIUM
)
74 , mnVerb(0), mbPlayFull(false)
78 class SdXMLEventContext
: public SvXMLImportContext
81 SdXMLEventContextData maData
;
85 SdXMLEventContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, const Reference
< XShape
>& rxShape
);
87 virtual SvXMLImportContextRef
CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
) override
;
88 virtual void EndElement() override
;
91 class XMLEventSoundContext
: public SvXMLImportContext
95 XMLEventSoundContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, SdXMLEventContext
* pParent
);
99 XMLEventSoundContext::XMLEventSoundContext( SvXMLImport
& rImp
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, SdXMLEventContext
* pParent
)
100 : SvXMLImportContext( rImp
, nPrfx
, rLocalName
)
102 if( pParent
&& nPrfx
== XML_NAMESPACE_PRESENTATION
&& IsXMLToken( rLocalName
, XML_SOUND
) )
104 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
105 for(sal_Int16 i
=0; i
< nAttrCount
; i
++)
107 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
108 OUString aAttrLocalName
;
109 sal_uInt16 nAttrPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aAttrLocalName
);
110 OUString sValue
= xAttrList
->getValueByIndex( i
);
112 switch( nAttrPrefix
)
114 case XML_NAMESPACE_XLINK
:
115 if( IsXMLToken( aAttrLocalName
, XML_HREF
) )
117 pParent
->maData
.msSoundURL
= rImp
.GetAbsoluteReference(sValue
);
120 case XML_NAMESPACE_PRESENTATION
:
121 if( IsXMLToken( aAttrLocalName
, XML_PLAY_FULL
) )
123 pParent
->maData
.mbPlayFull
= IsXMLToken( sValue
, XML_TRUE
);
130 SdXMLEventContext::SdXMLEventContext( SvXMLImport
& rImp
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, const Reference
< XShape
>& rxShape
)
131 : SvXMLImportContext(rImp
, nPrfx
, rLocalName
)
134 if( nPrfx
== XML_NAMESPACE_PRESENTATION
&& IsXMLToken( rLocalName
, XML_EVENT_LISTENER
) )
136 maData
.mbValid
= true;
138 else if( nPrfx
== XML_NAMESPACE_SCRIPT
&& IsXMLToken( rLocalName
, XML_EVENT_LISTENER
) )
140 maData
.mbScript
= true;
141 maData
.mbValid
= true;
150 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
151 for(sal_Int16 i
=0; (i
< nAttrCount
) && maData
.mbValid
; i
++)
153 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
154 OUString aAttrLocalName
;
155 sal_uInt16 nAttrPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aAttrLocalName
);
156 OUString sValue
= xAttrList
->getValueByIndex( i
);
158 switch( nAttrPrefix
)
160 case XML_NAMESPACE_PRESENTATION
:
161 if( IsXMLToken( aAttrLocalName
, XML_ACTION
) )
163 SvXMLUnitConverter::convertEnum( maData
.meClickAction
, sValue
, aXML_EventActions_EnumMap
);
165 if( IsXMLToken( aAttrLocalName
, XML_EFFECT
) )
167 SvXMLUnitConverter::convertEnum( maData
.meEffect
, sValue
, aXML_AnimationEffect_EnumMap
);
169 else if( IsXMLToken( aAttrLocalName
, XML_DIRECTION
) )
171 SvXMLUnitConverter::convertEnum( maData
.meDirection
, sValue
, aXML_AnimationDirection_EnumMap
);
173 else if( IsXMLToken( aAttrLocalName
, XML_START_SCALE
) )
176 if (::sax::Converter::convertPercent( nScale
, sValue
))
177 maData
.mnStartScale
= static_cast<sal_Int16
>(nScale
);
179 else if( IsXMLToken( aAttrLocalName
, XML_SPEED
) )
181 SvXMLUnitConverter::convertEnum( maData
.meSpeed
, sValue
, aXML_AnimationSpeed_EnumMap
);
183 else if( IsXMLToken( aAttrLocalName
, XML_VERB
) )
185 ::sax::Converter::convertNumber( maData
.mnVerb
, sValue
);
189 case XML_NAMESPACE_SCRIPT
:
190 if( IsXMLToken( aAttrLocalName
, XML_EVENT_NAME
) )
193 sal_uInt16 nScriptPrefix
=
194 GetImport().GetNamespaceMap().GetKeyByAttrName( sValue
, &sEventName
);
195 maData
.mbValid
= XML_NAMESPACE_DOM
== nScriptPrefix
&& sEventName
== "click";
197 else if( IsXMLToken( aAttrLocalName
, XML_LANGUAGE
) )
199 // language is not evaluated!
200 OUString aScriptLanguage
;
201 maData
.msLanguage
= sValue
;
202 sal_uInt16 nScriptPrefix
= rImp
.GetNamespaceMap().
203 GetKeyByAttrName( maData
.msLanguage
, &aScriptLanguage
);
204 if( XML_NAMESPACE_OOO
== nScriptPrefix
)
205 maData
.msLanguage
= aScriptLanguage
;
207 else if( IsXMLToken( aAttrLocalName
, XML_MACRO_NAME
) )
209 maData
.msMacroName
= sValue
;
213 case XML_NAMESPACE_XLINK
:
214 if( IsXMLToken( aAttrLocalName
, XML_HREF
) )
216 if ( maData
.mbScript
)
218 maData
.msMacroName
= sValue
;
222 const OUString
&rTmp
=
223 rImp
.GetAbsoluteReference(sValue
);
224 INetURLObject::translateToInternal( rTmp
, maData
.msBookmark
,
225 INetURLObject::DecodeMechanism::Unambiguous
);
233 maData
.mbValid
= !sEventName
.isEmpty();
235 if (!maData
.msMacroName
.isEmpty())
236 rImp
.NotifyMacroEventRead();
239 SvXMLImportContextRef
SdXMLEventContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
)
241 return new XMLEventSoundContext( GetImport(), nPrefix
, rLocalName
, xAttrList
, this );
244 void SdXMLEventContext::EndElement()
246 GetImport().GetShapeImport()->addShapeEvents(maData
);
249 void SdXMLEventContextData::ApplyProperties()
256 Reference
< XEventsSupplier
> xEventsSupplier( mxShape
, UNO_QUERY
);
257 if( !xEventsSupplier
.is() )
260 Reference
< XNameReplace
> xEvents( xEventsSupplier
->getEvents() );
261 SAL_WARN_IF( !xEvents
.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
265 OUString sAPIEventName
;
266 uno::Sequence
< beans::PropertyValue
> aProperties
;
268 sAPIEventName
= "OnClick";
271 meClickAction
= ClickAction_MACRO
;
273 sal_Int32 nPropertyCount
= 2;
274 switch( meClickAction
)
276 case ClickAction_NONE
:
277 case ClickAction_PREVPAGE
:
278 case ClickAction_NEXTPAGE
:
279 case ClickAction_FIRSTPAGE
:
280 case ClickAction_LASTPAGE
:
281 case ClickAction_INVISIBLE
:
282 case ClickAction_STOPPRESENTATION
:
284 case ClickAction_PROGRAM
:
285 case ClickAction_VERB
:
286 case ClickAction_BOOKMARK
:
287 case ClickAction_DOCUMENT
:
290 case ClickAction_MACRO
:
291 if ( msLanguage
.equalsIgnoreAsciiCase("starbasic") )
295 case ClickAction_SOUND
:
299 case ClickAction_VANISH
:
306 aProperties
.realloc( nPropertyCount
);
307 beans::PropertyValue
* pProperties
= aProperties
.getArray();
309 if( ClickAction_MACRO
== meClickAction
)
311 if ( msLanguage
.equalsIgnoreAsciiCase("starbasic") )
314 const OUString
& rApp
= GetXMLToken( XML_APPLICATION
);
315 const OUString
& rDoc
= GetXMLToken( XML_DOCUMENT
);
316 if( msMacroName
.getLength() > rApp
.getLength()+1 &&
317 msMacroName
.copy(0,rApp
.getLength()).equalsIgnoreAsciiCase( rApp
) &&
318 ':' == msMacroName
[rApp
.getLength()] )
320 sLibrary
= "StarOffice";
321 msMacroName
= msMacroName
.copy( rApp
.getLength()+1 );
323 else if( msMacroName
.getLength() > rDoc
.getLength()+1 &&
324 msMacroName
.copy(0,rDoc
.getLength()).equalsIgnoreAsciiCase( rDoc
) &&
325 ':' == msMacroName
[rDoc
.getLength()] )
328 msMacroName
= msMacroName
.copy( rDoc
.getLength()+1 );
331 pProperties
->Name
= "EventType";
332 pProperties
->Handle
= -1;
333 pProperties
->Value
<<= OUString( "StarBasic" );
334 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
337 pProperties
->Name
= "MacroName";
338 pProperties
->Handle
= -1;
339 pProperties
->Value
<<= msMacroName
;
340 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
343 pProperties
->Name
= "Library";
344 pProperties
->Handle
= -1;
345 pProperties
->Value
<<= sLibrary
;
346 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
350 pProperties
->Name
= "EventType";
351 pProperties
->Handle
= -1;
352 pProperties
->Value
<<= OUString( "Script" );
353 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
356 pProperties
->Name
= "Script";
357 pProperties
->Handle
= -1;
358 pProperties
->Value
<<= msMacroName
;
359 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
364 pProperties
->Name
= "EventType";
365 pProperties
->Handle
= -1;
366 pProperties
->Value
<<= OUString( "Presentation" );
367 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
370 // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same xml event
371 // so check here if it's really a bookmark or maybe a document
372 if( meClickAction
== ClickAction_BOOKMARK
)
374 if( !msBookmark
.startsWith( "#" ) )
375 meClickAction
= ClickAction_DOCUMENT
;
378 pProperties
->Name
= "ClickAction";
379 pProperties
->Handle
= -1;
380 pProperties
->Value
<<= meClickAction
;
381 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
384 switch( meClickAction
)
386 case ClickAction_NONE
:
387 case ClickAction_PREVPAGE
:
388 case ClickAction_NEXTPAGE
:
389 case ClickAction_FIRSTPAGE
:
390 case ClickAction_LASTPAGE
:
391 case ClickAction_INVISIBLE
:
392 case ClickAction_STOPPRESENTATION
:
395 case ClickAction_BOOKMARK
:
396 msBookmark
= msBookmark
.copy(1);
400 case ClickAction_DOCUMENT
:
401 case ClickAction_PROGRAM
:
402 pProperties
->Name
= "Bookmark";
403 pProperties
->Handle
= -1;
404 pProperties
->Value
<<= msBookmark
;
405 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
408 case ClickAction_VANISH
:
409 pProperties
->Name
= "Effect";
410 pProperties
->Handle
= -1;
411 pProperties
->Value
<<= ImplSdXMLgetEffect( meEffect
, meDirection
, mnStartScale
, true );
412 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
415 pProperties
->Name
= "Speed";
416 pProperties
->Handle
= -1;
417 pProperties
->Value
<<= meSpeed
;
418 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
423 case ClickAction_SOUND
:
424 pProperties
->Name
= "SoundURL";
425 pProperties
->Handle
= -1;
426 pProperties
->Value
<<= msSoundURL
;
427 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
430 pProperties
->Name
= "PlayFull";
431 pProperties
->Handle
= -1;
432 pProperties
->Value
<<= mbPlayFull
;
433 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
436 case ClickAction_VERB
:
437 pProperties
->Name
= "Verb";
438 pProperties
->Handle
= -1;
439 pProperties
->Value
<<= mnVerb
;
440 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
442 case ClickAction_MACRO
:
443 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
449 xEvents
->replaceByName( sAPIEventName
, uno::Any( aProperties
) );
455 SdXMLEventsContext::SdXMLEventsContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
,
456 const Reference
< XAttributeList
>&, const Reference
< XShape
>& rxShape
)
457 : SvXMLImportContext(rImport
, nPrfx
, rLocalName
), mxShape( rxShape
)
461 SdXMLEventsContext::~SdXMLEventsContext()
465 SvXMLImportContextRef
SdXMLEventsContext::CreateChildContext( sal_uInt16 nPrfx
, const OUString
& rLocalName
,
466 const css::uno::Reference
< css::xml::sax::XAttributeList
>& xAttrList
)
468 return new SdXMLEventContext( GetImport(), nPrfx
, rLocalName
, xAttrList
, mxShape
);
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */