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 <tools/debug.hxx>
21 #include <com/sun/star/document/XEventsSupplier.hpp>
22 #include <com/sun/star/container/XNameReplace.hpp>
23 #include <com/sun/star/presentation/AnimationSpeed.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/xml/sax/XAttributeList.hpp>
26 #include <com/sun/star/presentation/ClickAction.hpp>
27 #include <tools/urlobj.hxx>
28 #include <osl/diagnose.h>
30 #include <sax/tools/converter.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/xmlimp.hxx>
34 #include <xmloff/xmlnmspe.hxx>
35 #include <xmloff/xmluconv.hxx>
36 #include <xmloff/nmspmap.hxx>
37 #include "eventimp.hxx"
40 using namespace ::std
;
41 using namespace ::cppu
;
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::xml
;
44 using namespace ::com::sun::star::xml::sax
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::drawing
;
47 using namespace ::com::sun::star::beans
;
48 using namespace ::com::sun::star::lang
;
49 using namespace ::com::sun::star::document
;
50 using namespace ::com::sun::star::container
;
51 using namespace ::com::sun::star::presentation
;
52 using namespace ::xmloff::token
;
54 SvXMLEnumMapEntry
const aXML_EventActions_EnumMap
[] =
56 { XML_NONE
, ClickAction_NONE
},
57 { XML_PREVIOUS_PAGE
, ClickAction_PREVPAGE
},
58 { XML_NEXT_PAGE
, ClickAction_NEXTPAGE
},
59 { XML_FIRST_PAGE
, ClickAction_FIRSTPAGE
},
60 { XML_LAST_PAGE
, ClickAction_LASTPAGE
},
61 { XML_HIDE
, ClickAction_INVISIBLE
},
62 { XML_STOP
, ClickAction_STOPPRESENTATION
},
63 { XML_EXECUTE
, ClickAction_PROGRAM
},
64 { XML_SHOW
, ClickAction_BOOKMARK
},
65 { XML_SHOW
, ClickAction_DOCUMENT
},
66 { XML_EXECUTE_MACRO
, ClickAction_MACRO
},
67 { XML_VERB
, ClickAction_VERB
},
68 { XML_FADE_OUT
, ClickAction_VANISH
},
69 { XML_SOUND
, ClickAction_SOUND
},
70 { XML_TOKEN_INVALID
, 0 }
73 class SdXMLEventContext
: public SvXMLImportContext
76 com::sun::star::uno::Reference
< com::sun::star::drawing::XShape
> mxShape
;
81 SdXMLEventContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, const Reference
< XShape
>& rxShape
);
82 virtual ~SdXMLEventContext();
84 virtual SvXMLImportContext
* CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
) SAL_OVERRIDE
;
85 virtual void EndElement() SAL_OVERRIDE
;
89 ClickAction meClickAction
;
91 XMLEffectDirection meDirection
;
92 sal_Int16 mnStartScale
;
93 AnimationSpeed meSpeed
;
102 class XMLEventSoundContext
: public SvXMLImportContext
104 SdXMLEventContext
* mpParent
;
109 XMLEventSoundContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, SdXMLEventContext
* pParent
);
110 virtual ~XMLEventSoundContext();
113 TYPEINIT1( XMLEventSoundContext
, SvXMLImportContext
);
115 XMLEventSoundContext::XMLEventSoundContext( SvXMLImport
& rImp
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, SdXMLEventContext
* pParent
)
116 : SvXMLImportContext( rImp
, nPrfx
, rLocalName
), mpParent( pParent
)
118 if( mpParent
&& nPrfx
== XML_NAMESPACE_PRESENTATION
&& IsXMLToken( rLocalName
, XML_SOUND
) )
120 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
121 for(sal_Int16 i
=0; i
< nAttrCount
; i
++)
123 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
124 OUString aAttrLocalName
;
125 sal_uInt16 nAttrPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aAttrLocalName
);
126 OUString sValue
= xAttrList
->getValueByIndex( i
);
128 switch( nAttrPrefix
)
130 case XML_NAMESPACE_XLINK
:
131 if( IsXMLToken( aAttrLocalName
, XML_HREF
) )
133 mpParent
->msSoundURL
= rImp
.GetAbsoluteReference(sValue
);
136 case XML_NAMESPACE_PRESENTATION
:
137 if( IsXMLToken( aAttrLocalName
, XML_PLAY_FULL
) )
139 mpParent
->mbPlayFull
= IsXMLToken( sValue
, XML_TRUE
);
146 XMLEventSoundContext::~XMLEventSoundContext()
150 TYPEINIT1( SdXMLEventContext
, SvXMLImportContext
);
152 SdXMLEventContext::SdXMLEventContext( SvXMLImport
& rImp
, sal_uInt16 nPrfx
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
, const Reference
< XShape
>& rxShape
)
153 : SvXMLImportContext(rImp
, nPrfx
, rLocalName
)
154 , mxShape(rxShape
), mbValid(false), mbScript(false)
155 , meClickAction(ClickAction_NONE
), meEffect(EK_none
)
156 , meDirection(ED_none
), mnStartScale(100), meSpeed(AnimationSpeed_MEDIUM
)
157 , mnVerb(0), mbPlayFull(false)
159 static const char sXMLClickName
[] = "click";
161 if( nPrfx
== XML_NAMESPACE_PRESENTATION
&& IsXMLToken( rLocalName
, XML_EVENT_LISTENER
) )
165 else if( nPrfx
== XML_NAMESPACE_SCRIPT
&& IsXMLToken( rLocalName
, XML_EVENT_LISTENER
) )
177 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
178 for(sal_Int16 i
=0; (i
< nAttrCount
) && mbValid
; i
++)
180 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
181 OUString aAttrLocalName
;
182 sal_uInt16 nAttrPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aAttrLocalName
);
183 OUString sValue
= xAttrList
->getValueByIndex( i
);
185 switch( nAttrPrefix
)
187 case XML_NAMESPACE_PRESENTATION
:
188 if( IsXMLToken( aAttrLocalName
, XML_ACTION
) )
191 if( SvXMLUnitConverter::convertEnum( eEnum
, sValue
, aXML_EventActions_EnumMap
) )
192 meClickAction
= (ClickAction
)eEnum
;
194 if( IsXMLToken( aAttrLocalName
, XML_EFFECT
) )
197 if( SvXMLUnitConverter::convertEnum( eEnum
, sValue
, aXML_AnimationEffect_EnumMap
) )
198 meEffect
= (XMLEffect
)eEnum
;
200 else if( IsXMLToken( aAttrLocalName
, XML_DIRECTION
) )
203 if( SvXMLUnitConverter::convertEnum( eEnum
, sValue
, aXML_AnimationDirection_EnumMap
) )
204 meDirection
= (XMLEffectDirection
)eEnum
;
206 else if( IsXMLToken( aAttrLocalName
, XML_START_SCALE
) )
209 if (::sax::Converter::convertPercent( nScale
, sValue
))
210 mnStartScale
= (sal_Int16
)nScale
;
212 else if( IsXMLToken( aAttrLocalName
, XML_SPEED
) )
215 if( SvXMLUnitConverter::convertEnum( eEnum
, sValue
, aXML_AnimationSpeed_EnumMap
) )
216 meSpeed
= (AnimationSpeed
)eEnum
;
218 else if( IsXMLToken( aAttrLocalName
, XML_VERB
) )
220 ::sax::Converter::convertNumber( mnVerb
, sValue
);
224 case XML_NAMESPACE_SCRIPT
:
225 if( IsXMLToken( aAttrLocalName
, XML_EVENT_NAME
) )
228 sal_uInt16 nScriptPrefix
=
229 GetImport().GetNamespaceMap().GetKeyByAttrName( sValue
, &sEventName
);
230 mbValid
= XML_NAMESPACE_DOM
== nScriptPrefix
&& sEventName
== sXMLClickName
;
232 else if( IsXMLToken( aAttrLocalName
, XML_LANGUAGE
) )
234 // language is not evaluated!
235 OUString aScriptLanguage
;
237 sal_uInt16 nScriptPrefix
= rImp
.GetNamespaceMap().
238 GetKeyByAttrName( msLanguage
, &aScriptLanguage
);
239 if( XML_NAMESPACE_OOO
== nScriptPrefix
)
240 msLanguage
= aScriptLanguage
;
242 else if( IsXMLToken( aAttrLocalName
, XML_MACRO_NAME
) )
244 msMacroName
= sValue
;
248 case XML_NAMESPACE_XLINK
:
249 if( IsXMLToken( aAttrLocalName
, XML_HREF
) )
253 msMacroName
= sValue
;
257 const OUString
&rTmp
=
258 rImp
.GetAbsoluteReference(sValue
);
259 INetURLObject::translateToInternal( rTmp
, msBookmark
,
260 INetURLObject::DECODE_UNAMBIGUOUS
,
261 RTL_TEXTENCODING_UTF8
);
269 mbValid
= !sEventName
.isEmpty();
272 SdXMLEventContext::~SdXMLEventContext()
276 SvXMLImportContext
* SdXMLEventContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const Reference
< XAttributeList
>& xAttrList
)
278 return new XMLEventSoundContext( GetImport(), nPrefix
, rLocalName
, xAttrList
, this );
281 void SdXMLEventContext::EndElement()
288 Reference
< XEventsSupplier
> xEventsSupplier( mxShape
, UNO_QUERY
);
289 if( !xEventsSupplier
.is() )
292 Reference
< XNameReplace
> xEvents( xEventsSupplier
->getEvents() );
293 DBG_ASSERT( xEvents
.is(), "XEventsSupplier::getEvents() returned NULL" );
297 OUString sAPIEventName
;
298 uno::Sequence
< beans::PropertyValue
> aProperties
;
300 sAPIEventName
= "OnClick";
303 meClickAction
= ClickAction_MACRO
;
305 sal_Int32 nPropertyCount
= 2;
306 switch( meClickAction
)
308 case ClickAction_NONE
:
309 case ClickAction_PREVPAGE
:
310 case ClickAction_NEXTPAGE
:
311 case ClickAction_FIRSTPAGE
:
312 case ClickAction_LASTPAGE
:
313 case ClickAction_INVISIBLE
:
314 case ClickAction_STOPPRESENTATION
:
316 case ClickAction_PROGRAM
:
317 case ClickAction_VERB
:
318 case ClickAction_BOOKMARK
:
319 case ClickAction_DOCUMENT
:
322 case ClickAction_MACRO
:
323 if ( msLanguage
.equalsIgnoreAsciiCase("starbasic") )
327 case ClickAction_SOUND
:
331 case ClickAction_VANISH
:
338 aProperties
.realloc( nPropertyCount
);
339 beans::PropertyValue
* pProperties
= aProperties
.getArray();
341 if( ClickAction_MACRO
== meClickAction
)
343 if ( msLanguage
.equalsIgnoreAsciiCase("starbasic") )
346 const OUString
& rApp
= GetXMLToken( XML_APPLICATION
);
347 const OUString
& rDoc
= GetXMLToken( XML_DOCUMENT
);
348 if( msMacroName
.getLength() > rApp
.getLength()+1 &&
349 msMacroName
.copy(0,rApp
.getLength()).equalsIgnoreAsciiCase( rApp
) &&
350 ':' == msMacroName
[rApp
.getLength()] )
352 sLibrary
= "StarOffice";
353 msMacroName
= msMacroName
.copy( rApp
.getLength()+1 );
355 else if( msMacroName
.getLength() > rDoc
.getLength()+1 &&
356 msMacroName
.copy(0,rDoc
.getLength()).equalsIgnoreAsciiCase( rDoc
) &&
357 ':' == msMacroName
[rDoc
.getLength()] )
360 msMacroName
= msMacroName
.copy( rDoc
.getLength()+1 );
363 pProperties
->Name
= "EventType";
364 pProperties
->Handle
= -1;
365 pProperties
->Value
<<= OUString( "StarBasic" );
366 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
369 pProperties
->Name
= "MacroName";
370 pProperties
->Handle
= -1;
371 pProperties
->Value
<<= msMacroName
;
372 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
375 pProperties
->Name
= "Library";
376 pProperties
->Handle
= -1;
377 pProperties
->Value
<<= sLibrary
;
378 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
382 pProperties
->Name
= "EventType";
383 pProperties
->Handle
= -1;
384 pProperties
->Value
<<= OUString( "Script" );
385 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
388 pProperties
->Name
= "Script";
389 pProperties
->Handle
= -1;
390 pProperties
->Value
<<= msMacroName
;
391 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
396 pProperties
->Name
= "EventType";
397 pProperties
->Handle
= -1;
398 pProperties
->Value
<<= OUString( "Presentation" );
399 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
402 // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same xml event
403 // so check here if its really a bookmark or maybe a document
404 if( meClickAction
== ClickAction_BOOKMARK
)
406 if( !msBookmark
.startsWith( "#" ) )
407 meClickAction
= ClickAction_DOCUMENT
;
410 pProperties
->Name
= "ClickAction";
411 pProperties
->Handle
= -1;
412 pProperties
->Value
<<= meClickAction
;
413 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
416 switch( meClickAction
)
418 case ClickAction_NONE
:
419 case ClickAction_PREVPAGE
:
420 case ClickAction_NEXTPAGE
:
421 case ClickAction_FIRSTPAGE
:
422 case ClickAction_LASTPAGE
:
423 case ClickAction_INVISIBLE
:
424 case ClickAction_STOPPRESENTATION
:
427 case ClickAction_BOOKMARK
:
428 msBookmark
= msBookmark
.copy(1);
430 // Note: no break here!!!
432 case ClickAction_DOCUMENT
:
433 case ClickAction_PROGRAM
:
434 pProperties
->Name
= "Bookmark";
435 pProperties
->Handle
= -1;
436 pProperties
->Value
<<= msBookmark
;
437 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
440 case ClickAction_VANISH
:
441 pProperties
->Name
= "Effect";
442 pProperties
->Handle
= -1;
443 pProperties
->Value
<<= ImplSdXMLgetEffect( meEffect
, meDirection
, mnStartScale
, true );
444 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
447 pProperties
->Name
= "Speed";
448 pProperties
->Handle
= -1;
449 pProperties
->Value
<<= meSpeed
;
450 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
453 // NOTE: no break here!!!
455 case ClickAction_SOUND
:
456 pProperties
->Name
= "SoundURL";
457 pProperties
->Handle
= -1;
458 pProperties
->Value
<<= msSoundURL
;
459 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
462 pProperties
->Name
= "PlayFull";
463 pProperties
->Handle
= -1;
464 pProperties
->Value
<<= mbPlayFull
;
465 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
468 case ClickAction_VERB
:
469 pProperties
->Name
= "Verb";
470 pProperties
->Handle
= -1;
471 pProperties
->Value
<<= mnVerb
;
472 pProperties
->State
= beans::PropertyState_DIRECT_VALUE
;
474 case ClickAction_MACRO
:
475 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
481 xEvents
->replaceByName( sAPIEventName
, uno::Any( aProperties
) );
486 TYPEINIT1( SdXMLEventsContext
, SvXMLImportContext
);
488 SdXMLEventsContext::SdXMLEventsContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLocalName
,
489 const Reference
< XAttributeList
>&, const Reference
< XShape
>& rxShape
)
490 : SvXMLImportContext(rImport
, nPrfx
, rLocalName
), mxShape( rxShape
)
494 SdXMLEventsContext::~SdXMLEventsContext()
498 SvXMLImportContext
* SdXMLEventsContext::CreateChildContext( sal_uInt16 nPrfx
, const OUString
& rLocalName
,
499 const com::sun::star::uno::Reference
< com::sun::star::xml::sax::XAttributeList
>& xAttrList
)
501 return new SdXMLEventContext( GetImport(), nPrfx
, rLocalName
, xAttrList
, mxShape
);
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */