tdf#143148 Use pragma once instead of include guards
[LibreOffice.git] / xmloff / source / draw / eventimp.cxx
blob9e90de023c6d03d27790f7c6b386d23482842c6d
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 <tools/urlobj.hxx>
23 #include <osl/diagnose.h>
24 #include <sal/log.hxx>
25 #include <o3tl/string_view.hxx>
27 #include <sax/tools/converter.hxx>
29 #include <xmloff/xmltoken.hxx>
30 #include <xmloff/xmlimp.hxx>
31 #include <xmloff/xmlnamespace.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/namespacemap.hxx>
34 #include "eventimp.hxx"
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::xml;
38 using namespace ::com::sun::star::xml::sax;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::drawing;
41 using namespace ::com::sun::star::beans;
42 using namespace ::com::sun::star::document;
43 using namespace ::com::sun::star::container;
44 using namespace ::com::sun::star::presentation;
45 using namespace ::xmloff::token;
47 SvXMLEnumMapEntry<ClickAction> const aXML_EventActions_EnumMap[] =
49 { XML_NONE, ClickAction_NONE },
50 { XML_PREVIOUS_PAGE, ClickAction_PREVPAGE },
51 { XML_NEXT_PAGE, ClickAction_NEXTPAGE },
52 { XML_FIRST_PAGE, ClickAction_FIRSTPAGE },
53 { XML_LAST_PAGE, ClickAction_LASTPAGE },
54 { XML_HIDE, ClickAction_INVISIBLE },
55 { XML_STOP, ClickAction_STOPPRESENTATION },
56 { XML_EXECUTE, ClickAction_PROGRAM },
57 { XML_SHOW, ClickAction_BOOKMARK },
58 { XML_SHOW, ClickAction_DOCUMENT },
59 { XML_EXECUTE_MACRO, ClickAction_MACRO },
60 { XML_VERB, ClickAction_VERB },
61 { XML_FADE_OUT, ClickAction_VANISH },
62 { XML_SOUND, ClickAction_SOUND },
63 { XML_TOKEN_INVALID, ClickAction(0) }
66 SdXMLEventContextData::SdXMLEventContextData(const Reference< XShape >& rxShape)
67 : mxShape(rxShape), mbValid(false), mbScript(false)
68 , meClickAction(ClickAction_NONE), meEffect(EK_none)
69 , meDirection(ED_none), mnStartScale(100), meSpeed(AnimationSpeed_MEDIUM)
70 , mnVerb(0), mbPlayFull(false)
74 namespace {
76 class SdXMLEventContext : public SvXMLImportContext
78 public:
79 SdXMLEventContextData maData;
81 public:
83 SdXMLEventContext( SvXMLImport& rImport, sal_Int32 nElement, const Reference< XFastAttributeList>& xAttrList, const Reference< XShape >& rxShape );
85 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
86 sal_Int32 nElement,
87 const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
88 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
91 class XMLEventSoundContext : public SvXMLImportContext
93 public:
95 XMLEventSoundContext( SvXMLImport& rImport, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent );
100 XMLEventSoundContext::XMLEventSoundContext( SvXMLImport& rImp, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent )
101 : SvXMLImportContext( rImp )
103 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
105 switch( aIter.getToken() )
107 case XML_ELEMENT(XLINK, XML_HREF):
108 pParent->maData.msSoundURL = rImp.GetAbsoluteReference(aIter.toString());
109 break;
110 case XML_ELEMENT(PRESENTATION, XML_PLAY_FULL):
111 pParent->maData.mbPlayFull = IsXMLToken( aIter, XML_TRUE );
112 break;
113 default:
114 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
119 SdXMLEventContext::SdXMLEventContext( SvXMLImport& rImp,
120 sal_Int32 nElement,
121 const Reference< XFastAttributeList >& xAttrList, const Reference< XShape >& rxShape )
122 : SvXMLImportContext(rImp)
123 , maData(rxShape)
125 if( nElement == XML_ELEMENT(PRESENTATION, XML_EVENT_LISTENER) )
127 maData.mbValid = true;
129 else if( nElement == XML_ELEMENT(SCRIPT, XML_EVENT_LISTENER) )
131 maData.mbScript = true;
132 maData.mbValid = true;
134 else
136 return;
139 // read attributes
140 OUString sEventName;
141 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
143 switch( aIter.getToken() )
145 case XML_ELEMENT(PRESENTATION, XML_ACTION):
146 SvXMLUnitConverter::convertEnum( maData.meClickAction, aIter.toView(), aXML_EventActions_EnumMap );
147 break;
148 case XML_ELEMENT(PRESENTATION, XML_EFFECT):
149 SvXMLUnitConverter::convertEnum( maData.meEffect, aIter.toView(), aXML_AnimationEffect_EnumMap );
150 break;
151 case XML_ELEMENT(PRESENTATION, XML_DIRECTION):
152 SvXMLUnitConverter::convertEnum( maData.meDirection, aIter.toView(), aXML_AnimationDirection_EnumMap );
153 break;
154 case XML_ELEMENT(PRESENTATION, XML_START_SCALE):
156 sal_Int32 nScale;
157 if (::sax::Converter::convertPercent( nScale, aIter.toView() ))
158 maData.mnStartScale = static_cast<sal_Int16>(nScale);
160 break;
161 case XML_ELEMENT(PRESENTATION, XML_SPEED):
162 SvXMLUnitConverter::convertEnum( maData.meSpeed, aIter.toView(), aXML_AnimationSpeed_EnumMap );
163 break;
164 case XML_ELEMENT(PRESENTATION, XML_VERB):
165 ::sax::Converter::convertNumber( maData.mnVerb, aIter.toView() );
166 break;
167 case XML_ELEMENT(SCRIPT, XML_EVENT_NAME):
169 sEventName = aIter.toString();
170 sal_uInt16 nScriptPrefix =
171 GetImport().GetNamespaceMap().GetKeyByAttrValueQName(sEventName, &sEventName);
172 maData.mbValid = XML_NAMESPACE_DOM == nScriptPrefix && sEventName == "click";
174 break;
175 case XML_ELEMENT(SCRIPT, XML_LANGUAGE):
177 // language is not evaluated!
178 OUString aScriptLanguage;
179 maData.msLanguage = aIter.toString();
180 sal_uInt16 nScriptPrefix = rImp.GetNamespaceMap().
181 GetKeyByAttrValueQName(maData.msLanguage, &aScriptLanguage);
182 if( XML_NAMESPACE_OOO == nScriptPrefix )
183 maData.msLanguage = aScriptLanguage;
185 break;
186 case XML_ELEMENT(SCRIPT, XML_MACRO_NAME):
187 maData.msMacroName = aIter.toString();
188 break;
189 case XML_ELEMENT(XLINK, XML_HREF):
191 if ( maData.mbScript )
193 maData.msMacroName = aIter.toString();
195 else
197 const OUString &rTmp =
198 rImp.GetAbsoluteReference(aIter.toString());
199 INetURLObject::translateToInternal( rTmp, maData.msBookmark,
200 INetURLObject::DecodeMechanism::Unambiguous );
203 break;
207 if( maData.mbValid )
208 maData.mbValid = !sEventName.isEmpty();
210 if (!maData.msMacroName.isEmpty())
211 rImp.NotifyMacroEventRead();
214 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLEventContext::createFastChildContext(
215 sal_Int32 nElement,
216 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
218 if( nElement == XML_ELEMENT(PRESENTATION, XML_SOUND) )
219 return new XMLEventSoundContext( GetImport(), xAttrList, this );
220 else
221 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
222 return nullptr;
225 void SdXMLEventContext::endFastElement(sal_Int32 )
227 GetImport().GetShapeImport()->addShapeEvents(maData);
230 void SdXMLEventContextData::ApplyProperties()
232 if( !mbValid )
233 return;
237 Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
238 if( !xEventsSupplier.is() )
239 break;
241 Reference< XNameReplace > xEvents( xEventsSupplier->getEvents() );
242 SAL_WARN_IF( !xEvents.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
243 if( !xEvents.is() )
244 break;
246 OUString sAPIEventName;
247 uno::Sequence< beans::PropertyValue > aProperties;
249 sAPIEventName = "OnClick";
251 if( mbScript )
252 meClickAction = ClickAction_MACRO;
254 sal_Int32 nPropertyCount = 2;
255 switch( meClickAction )
257 case ClickAction_NONE:
258 case ClickAction_PREVPAGE:
259 case ClickAction_NEXTPAGE:
260 case ClickAction_FIRSTPAGE:
261 case ClickAction_LASTPAGE:
262 case ClickAction_INVISIBLE:
263 case ClickAction_STOPPRESENTATION:
264 break;
265 case ClickAction_PROGRAM:
266 case ClickAction_VERB:
267 case ClickAction_BOOKMARK:
268 case ClickAction_DOCUMENT:
269 nPropertyCount += 1;
270 break;
271 case ClickAction_MACRO:
272 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
273 nPropertyCount += 1;
274 break;
276 case ClickAction_SOUND:
277 nPropertyCount += 2;
278 break;
280 case ClickAction_VANISH:
281 nPropertyCount += 4;
282 break;
283 default:
284 break;
287 aProperties.realloc( nPropertyCount );
288 beans::PropertyValue* pProperties = aProperties.getArray();
290 if( ClickAction_MACRO == meClickAction )
292 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
294 OUString sLibrary;
295 const OUString& rApp = GetXMLToken( XML_APPLICATION );
296 const OUString& rDoc = GetXMLToken( XML_DOCUMENT );
297 if( msMacroName.getLength() > rApp.getLength()+1 &&
298 o3tl::equalsIgnoreAsciiCase(msMacroName.subView(0,rApp.getLength()), rApp) &&
299 ':' == msMacroName[rApp.getLength()] )
301 sLibrary = "StarOffice";
302 msMacroName = msMacroName.copy( rApp.getLength()+1 );
304 else if( msMacroName.getLength() > rDoc.getLength()+1 &&
305 o3tl::equalsIgnoreAsciiCase(msMacroName.subView(0,rDoc.getLength()), rDoc) &&
306 ':' == msMacroName[rDoc.getLength()] )
308 sLibrary = rDoc;
309 msMacroName = msMacroName.copy( rDoc.getLength()+1 );
312 pProperties->Name = "EventType";
313 pProperties->Handle = -1;
314 pProperties->Value <<= u"StarBasic"_ustr;
315 pProperties->State = beans::PropertyState_DIRECT_VALUE;
316 pProperties++;
318 pProperties->Name = "MacroName";
319 pProperties->Handle = -1;
320 pProperties->Value <<= msMacroName;
321 pProperties->State = beans::PropertyState_DIRECT_VALUE;
322 pProperties++;
324 pProperties->Name = "Library";
325 pProperties->Handle = -1;
326 pProperties->Value <<= sLibrary;
327 pProperties->State = beans::PropertyState_DIRECT_VALUE;
329 else
331 pProperties->Name = "EventType";
332 pProperties->Handle = -1;
333 pProperties->Value <<= u"Script"_ustr;
334 pProperties->State = beans::PropertyState_DIRECT_VALUE;
335 pProperties++;
337 pProperties->Name = "Script";
338 pProperties->Handle = -1;
339 pProperties->Value <<= msMacroName;
340 pProperties->State = beans::PropertyState_DIRECT_VALUE;
343 else
345 pProperties->Name = "EventType";
346 pProperties->Handle = -1;
347 pProperties->Value <<= u"Presentation"_ustr;
348 pProperties->State = beans::PropertyState_DIRECT_VALUE;
349 pProperties++;
351 // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same xml event
352 // so check here if it's really a bookmark or maybe a document
353 if( meClickAction == ClickAction_BOOKMARK )
355 if( !msBookmark.startsWith( "#" ) )
356 meClickAction = ClickAction_DOCUMENT;
359 pProperties->Name = "ClickAction";
360 pProperties->Handle = -1;
361 pProperties->Value <<= meClickAction;
362 pProperties->State = beans::PropertyState_DIRECT_VALUE;
363 pProperties++;
365 switch( meClickAction )
367 case ClickAction_NONE:
368 case ClickAction_PREVPAGE:
369 case ClickAction_NEXTPAGE:
370 case ClickAction_FIRSTPAGE:
371 case ClickAction_LASTPAGE:
372 case ClickAction_INVISIBLE:
373 case ClickAction_STOPPRESENTATION:
374 break;
376 case ClickAction_BOOKMARK:
377 msBookmark = msBookmark.copy(1);
379 [[fallthrough]];
381 case ClickAction_DOCUMENT:
382 case ClickAction_PROGRAM:
383 pProperties->Name = "Bookmark";
384 pProperties->Handle = -1;
385 pProperties->Value <<= msBookmark;
386 pProperties->State = beans::PropertyState_DIRECT_VALUE;
387 break;
389 case ClickAction_VANISH:
390 pProperties->Name = "Effect";
391 pProperties->Handle = -1;
392 pProperties->Value <<= ImplSdXMLgetEffect( meEffect, meDirection, mnStartScale, true );
393 pProperties->State = beans::PropertyState_DIRECT_VALUE;
394 pProperties++;
396 pProperties->Name = "Speed";
397 pProperties->Handle = -1;
398 pProperties->Value <<= meSpeed;
399 pProperties->State = beans::PropertyState_DIRECT_VALUE;
400 pProperties++;
402 [[fallthrough]];
404 case ClickAction_SOUND:
405 pProperties->Name = "SoundURL";
406 pProperties->Handle = -1;
407 pProperties->Value <<= msSoundURL;
408 pProperties->State = beans::PropertyState_DIRECT_VALUE;
409 pProperties++;
411 pProperties->Name = "PlayFull";
412 pProperties->Handle = -1;
413 pProperties->Value <<= mbPlayFull;
414 pProperties->State = beans::PropertyState_DIRECT_VALUE;
415 break;
417 case ClickAction_VERB:
418 pProperties->Name = "Verb";
419 pProperties->Handle = -1;
420 pProperties->Value <<= mnVerb;
421 pProperties->State = beans::PropertyState_DIRECT_VALUE;
422 break;
423 case ClickAction_MACRO:
424 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
425 break;
426 default:
427 break;
430 xEvents->replaceByName( sAPIEventName, uno::Any( aProperties ) );
432 } while(false);
436 SdXMLEventsContext::SdXMLEventsContext( SvXMLImport& rImport, const Reference< XShape >& rxShape)
437 : SvXMLImportContext(rImport), mxShape( rxShape )
441 SdXMLEventsContext::~SdXMLEventsContext()
445 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLEventsContext::createFastChildContext(
446 sal_Int32 nElement,
447 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
449 return new SdXMLEventContext( GetImport(), nElement, xAttrList, mxShape );
452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */