add notify for script use
[LibreOffice.git] / xmloff / source / draw / eventimp.cxx
blobfcc36f946ff18ce28f3b218cee81df0233846c34
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 <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
80 public:
81 SdXMLEventContextData maData;
83 public:
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
93 public:
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);
119 break;
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)
132 , maData(rxShape)
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;
143 else
145 return;
148 // read attributes
149 OUString sEventName;
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 ) )
175 sal_Int32 nScale;
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 );
187 break;
189 case XML_NAMESPACE_SCRIPT:
190 if( IsXMLToken( aAttrLocalName, XML_EVENT_NAME ) )
192 sEventName = sValue;
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;
211 break;
213 case XML_NAMESPACE_XLINK:
214 if( IsXMLToken( aAttrLocalName, XML_HREF ) )
216 if ( maData.mbScript )
218 maData.msMacroName = sValue;
220 else
222 const OUString &rTmp =
223 rImp.GetAbsoluteReference(sValue);
224 INetURLObject::translateToInternal( rTmp, maData.msBookmark,
225 INetURLObject::DecodeMechanism::Unambiguous );
228 break;
232 if( maData.mbValid )
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()
251 if( !mbValid )
252 return;
256 Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
257 if( !xEventsSupplier.is() )
258 break;
260 Reference< XNameReplace > xEvents( xEventsSupplier->getEvents() );
261 SAL_WARN_IF( !xEvents.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
262 if( !xEvents.is() )
263 break;
265 OUString sAPIEventName;
266 uno::Sequence< beans::PropertyValue > aProperties;
268 sAPIEventName = "OnClick";
270 if( mbScript )
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:
283 break;
284 case ClickAction_PROGRAM:
285 case ClickAction_VERB:
286 case ClickAction_BOOKMARK:
287 case ClickAction_DOCUMENT:
288 nPropertyCount += 1;
289 break;
290 case ClickAction_MACRO:
291 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
292 nPropertyCount += 1;
293 break;
295 case ClickAction_SOUND:
296 nPropertyCount += 2;
297 break;
299 case ClickAction_VANISH:
300 nPropertyCount += 4;
301 break;
302 default:
303 break;
306 aProperties.realloc( nPropertyCount );
307 beans::PropertyValue* pProperties = aProperties.getArray();
309 if( ClickAction_MACRO == meClickAction )
311 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
313 OUString sLibrary;
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()] )
327 sLibrary = rDoc;
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;
335 pProperties++;
337 pProperties->Name = "MacroName";
338 pProperties->Handle = -1;
339 pProperties->Value <<= msMacroName;
340 pProperties->State = beans::PropertyState_DIRECT_VALUE;
341 pProperties++;
343 pProperties->Name = "Library";
344 pProperties->Handle = -1;
345 pProperties->Value <<= sLibrary;
346 pProperties->State = beans::PropertyState_DIRECT_VALUE;
348 else
350 pProperties->Name = "EventType";
351 pProperties->Handle = -1;
352 pProperties->Value <<= OUString( "Script" );
353 pProperties->State = beans::PropertyState_DIRECT_VALUE;
354 pProperties++;
356 pProperties->Name = "Script";
357 pProperties->Handle = -1;
358 pProperties->Value <<= msMacroName;
359 pProperties->State = beans::PropertyState_DIRECT_VALUE;
362 else
364 pProperties->Name = "EventType";
365 pProperties->Handle = -1;
366 pProperties->Value <<= OUString( "Presentation" );
367 pProperties->State = beans::PropertyState_DIRECT_VALUE;
368 pProperties++;
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;
382 pProperties++;
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:
393 break;
395 case ClickAction_BOOKMARK:
396 msBookmark = msBookmark.copy(1);
398 [[fallthrough]];
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;
406 break;
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;
413 pProperties++;
415 pProperties->Name = "Speed";
416 pProperties->Handle = -1;
417 pProperties->Value <<= meSpeed;
418 pProperties->State = beans::PropertyState_DIRECT_VALUE;
419 pProperties++;
421 [[fallthrough]];
423 case ClickAction_SOUND:
424 pProperties->Name = "SoundURL";
425 pProperties->Handle = -1;
426 pProperties->Value <<= msSoundURL;
427 pProperties->State = beans::PropertyState_DIRECT_VALUE;
428 pProperties++;
430 pProperties->Name = "PlayFull";
431 pProperties->Handle = -1;
432 pProperties->Value <<= mbPlayFull;
433 pProperties->State = beans::PropertyState_DIRECT_VALUE;
434 break;
436 case ClickAction_VERB:
437 pProperties->Name = "Verb";
438 pProperties->Handle = -1;
439 pProperties->Value <<= mnVerb;
440 pProperties->State = beans::PropertyState_DIRECT_VALUE;
441 break;
442 case ClickAction_MACRO:
443 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
444 break;
445 default:
446 break;
449 xEvents->replaceByName( sAPIEventName, uno::Any( aProperties ) );
451 } while(false);
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: */