bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / draw / eventimp.cxx
blob49d6cdbc860136e54730eec2a252fe5885e0f261
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
38 #include "anim.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
75 private:
76 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > mxShape;
78 public:
79 TYPEINFO_OVERRIDE();
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;
87 bool mbValid;
88 bool mbScript;
89 ClickAction meClickAction;
90 XMLEffect meEffect;
91 XMLEffectDirection meDirection;
92 sal_Int16 mnStartScale;
93 AnimationSpeed meSpeed;
94 sal_Int32 mnVerb;
95 OUString msSoundURL;
96 bool mbPlayFull;
97 OUString msMacroName;
98 OUString msBookmark;
99 OUString msLanguage;
102 class XMLEventSoundContext : public SvXMLImportContext
104 SdXMLEventContext* mpParent;
106 public:
107 TYPEINFO_OVERRIDE();
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);
135 break;
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 ) )
163 mbValid = true;
165 else if( nPrfx == XML_NAMESPACE_SCRIPT && IsXMLToken( rLocalName, XML_EVENT_LISTENER ) )
167 mbScript = true;
168 mbValid = true;
170 else
172 return;
175 // read attributes
176 OUString sEventName;
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 ) )
190 sal_uInt16 eEnum;
191 if( SvXMLUnitConverter::convertEnum( eEnum, sValue, aXML_EventActions_EnumMap ) )
192 meClickAction = (ClickAction)eEnum;
194 if( IsXMLToken( aAttrLocalName, XML_EFFECT ) )
196 sal_uInt16 eEnum;
197 if( SvXMLUnitConverter::convertEnum( eEnum, sValue, aXML_AnimationEffect_EnumMap ) )
198 meEffect = (XMLEffect)eEnum;
200 else if( IsXMLToken( aAttrLocalName, XML_DIRECTION ) )
202 sal_uInt16 eEnum;
203 if( SvXMLUnitConverter::convertEnum( eEnum, sValue, aXML_AnimationDirection_EnumMap ) )
204 meDirection = (XMLEffectDirection)eEnum;
206 else if( IsXMLToken( aAttrLocalName, XML_START_SCALE ) )
208 sal_Int32 nScale;
209 if (::sax::Converter::convertPercent( nScale, sValue ))
210 mnStartScale = (sal_Int16)nScale;
212 else if( IsXMLToken( aAttrLocalName, XML_SPEED ) )
214 sal_uInt16 eEnum;
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 );
222 break;
224 case XML_NAMESPACE_SCRIPT:
225 if( IsXMLToken( aAttrLocalName, XML_EVENT_NAME ) )
227 sEventName = sValue;
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;
236 msLanguage = sValue;
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;
246 break;
248 case XML_NAMESPACE_XLINK:
249 if( IsXMLToken( aAttrLocalName, XML_HREF ) )
251 if ( mbScript )
253 msMacroName = sValue;
255 else
257 const OUString &rTmp =
258 rImp.GetAbsoluteReference(sValue);
259 INetURLObject::translateToInternal( rTmp, msBookmark,
260 INetURLObject::DECODE_UNAMBIGUOUS,
261 RTL_TEXTENCODING_UTF8 );
264 break;
268 if( mbValid )
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()
283 if( !mbValid )
284 return;
288 Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
289 if( !xEventsSupplier.is() )
290 break;
292 Reference< XNameReplace > xEvents( xEventsSupplier->getEvents() );
293 DBG_ASSERT( xEvents.is(), "XEventsSupplier::getEvents() returned NULL" );
294 if( !xEvents.is() )
295 break;
297 OUString sAPIEventName;
298 uno::Sequence< beans::PropertyValue > aProperties;
300 sAPIEventName = "OnClick";
302 if( mbScript )
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:
315 break;
316 case ClickAction_PROGRAM:
317 case ClickAction_VERB:
318 case ClickAction_BOOKMARK:
319 case ClickAction_DOCUMENT:
320 nPropertyCount += 1;
321 break;
322 case ClickAction_MACRO:
323 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
324 nPropertyCount += 1;
325 break;
327 case ClickAction_SOUND:
328 nPropertyCount += 2;
329 break;
331 case ClickAction_VANISH:
332 nPropertyCount += 4;
333 break;
334 default:
335 break;
338 aProperties.realloc( nPropertyCount );
339 beans::PropertyValue* pProperties = aProperties.getArray();
341 if( ClickAction_MACRO == meClickAction )
343 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
345 OUString sLibrary;
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()] )
359 sLibrary = rDoc;
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;
367 pProperties++;
369 pProperties->Name = "MacroName";
370 pProperties->Handle = -1;
371 pProperties->Value <<= msMacroName;
372 pProperties->State = beans::PropertyState_DIRECT_VALUE;
373 pProperties++;
375 pProperties->Name = "Library";
376 pProperties->Handle = -1;
377 pProperties->Value <<= sLibrary;
378 pProperties->State = beans::PropertyState_DIRECT_VALUE;
380 else
382 pProperties->Name = "EventType";
383 pProperties->Handle = -1;
384 pProperties->Value <<= OUString( "Script" );
385 pProperties->State = beans::PropertyState_DIRECT_VALUE;
386 pProperties++;
388 pProperties->Name = "Script";
389 pProperties->Handle = -1;
390 pProperties->Value <<= msMacroName;
391 pProperties->State = beans::PropertyState_DIRECT_VALUE;
394 else
396 pProperties->Name = "EventType";
397 pProperties->Handle = -1;
398 pProperties->Value <<= OUString( "Presentation" );
399 pProperties->State = beans::PropertyState_DIRECT_VALUE;
400 pProperties++;
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;
414 pProperties++;
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:
425 break;
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;
438 break;
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;
445 pProperties++;
447 pProperties->Name = "Speed";
448 pProperties->Handle = -1;
449 pProperties->Value <<= meSpeed;
450 pProperties->State = beans::PropertyState_DIRECT_VALUE;
451 pProperties++;
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;
460 pProperties++;
462 pProperties->Name = "PlayFull";
463 pProperties->Handle = -1;
464 pProperties->Value <<= mbPlayFull;
465 pProperties->State = beans::PropertyState_DIRECT_VALUE;
466 break;
468 case ClickAction_VERB:
469 pProperties->Name = "Verb";
470 pProperties->Handle = -1;
471 pProperties->Value <<= mnVerb;
472 pProperties->State = beans::PropertyState_DIRECT_VALUE;
473 break;
474 case ClickAction_MACRO:
475 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
476 break;
477 default:
478 break;
481 xEvents->replaceByName( sAPIEventName, uno::Any( aProperties ) );
483 } while(false);
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: */