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 <xmloff/XMLEventExport.hxx>
22 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/document/XEventsSupplier.hpp>
26 #include <com/sun/star/container/XNameReplace.hpp>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <xmloff/xmlexp.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlnamespace.hxx>
32 #include <xmloff/namespacemap.hxx>
35 using namespace ::com::sun::star::uno
;
37 using ::com::sun::star::beans::PropertyValue
;
38 using ::com::sun::star::document::XEventsSupplier
;
39 using ::com::sun::star::container::XNameReplace
;
40 using ::com::sun::star::container::XNameAccess
;
41 using ::xmloff::token::XML_EVENT_LISTENERS
;
43 XMLEventExport::XMLEventExport(SvXMLExport
& rExp
) :
45 m_bExtNamespace(false)
49 XMLEventExport::~XMLEventExport()
51 // delete all handlers
52 m_aHandlerMap
.clear();
55 void XMLEventExport::AddHandler( const OUString
& rName
,
56 std::unique_ptr
<XMLEventExportHandler
> pHandler
)
59 m_aHandlerMap
[rName
] = std::move(pHandler
);
62 void XMLEventExport::AddTranslationTable(
63 const XMLEventNameTranslation
* pTransTable
)
65 if (nullptr != pTransTable
)
67 // put translation table into map
68 for(const XMLEventNameTranslation
* pTrans
= pTransTable
;
69 !pTrans
->sAPIName
.isEmpty();
72 m_aNameTranslationMap
[pTrans
->sAPIName
] =
73 XMLEventName(pTrans
->nPrefix
, pTrans
->sXMLName
);
79 void XMLEventExport::Export( Reference
<XEventsSupplier
> const & rSupplier
,
84 Export(rSupplier
->getEvents(), bWhitespace
);
86 // else: no supplier, no export -> ignore!
89 void XMLEventExport::Export( Reference
<XNameReplace
> const & rReplace
,
92 Reference
<XNameAccess
> xAccess(rReplace
);
93 Export(xAccess
, bWhitespace
);
96 void XMLEventExport::Export( Reference
<XNameAccess
> const & rAccess
,
99 // early out if we don't actually get any events
105 // have we already processed an element?
106 bool bStarted
= false;
108 // iterate over all event types
109 const Sequence
<OUString
> aNames
= rAccess
->getElementNames();
110 for(const auto& rName
: aNames
)
113 NameMap::iterator aIter
= m_aNameTranslationMap
.find(rName
);
114 if (aIter
!= m_aNameTranslationMap
.end())
116 const XMLEventName
& rXmlName
= aIter
->second
;
118 // get PropertyValues for this event
119 Any aAny
= rAccess
->getByName( rName
);
120 Sequence
<PropertyValue
> aValues
;
123 // now export the current event
124 ExportEvent( aValues
, rXmlName
, bWhitespace
, bStarted
);
128 // don't proceed further
129 SAL_WARN("xmloff", "Unknown event name:" << rName
);
133 // close <script:events> element (if it was opened before)
136 EndElement(bWhitespace
);
140 void XMLEventExport::ExportExt( Reference
<XNameAccess
> const & rAccess
)
142 // set bExtNamespace flag to use XML_NAMESPACE_OFFICE_EXT namespace
143 // for events element (not for child elements)
144 m_bExtNamespace
= true;
146 m_bExtNamespace
= false; // reset for future Export calls
149 /// export a singular event and write <office:events> container
150 void XMLEventExport::ExportSingleEvent(
151 const Sequence
<PropertyValue
>& rEventValues
,
152 const OUString
& rApiEventName
,
153 bool bUseWhitespace
)
155 // translate the name
156 NameMap::iterator aIter
= m_aNameTranslationMap
.find(rApiEventName
);
157 if (aIter
!= m_aNameTranslationMap
.end())
159 const XMLEventName
& rXmlName
= aIter
->second
;
161 // export the event ...
162 bool bStarted
= false;
163 ExportEvent( rEventValues
, rXmlName
, bUseWhitespace
, bStarted
);
165 // ... and close the container element (if necessary)
168 EndElement(bUseWhitespace
);
173 // don't proceed further
174 SAL_WARN("xmloff", "Unknown event name:" << rApiEventName
);
179 /// export a single event
180 void XMLEventExport::ExportEvent(
181 const Sequence
<PropertyValue
>& rEventValues
,
182 const XMLEventName
& rXmlEventName
,
186 // search for EventType value and then delegate to EventHandler
187 const PropertyValue
* pValue
= std::find_if(rEventValues
.begin(), rEventValues
.end(),
188 [](const PropertyValue
& rValue
) { return u
"EventType" == rValue
.Name
; });
190 if (pValue
== rEventValues
.end())
193 // found! Now find handler and delegate
195 pValue
->Value
>>= sType
;
197 if (m_aHandlerMap
.count(sType
))
201 // OK, we have't yet exported the enclosing
202 // element. So we do that now.
204 StartElement(bUseWhitespace
);
207 OUString
aEventQName(
208 m_rExport
.GetNamespaceMap().GetQNameByKey(
209 rXmlEventName
.m_nPrefix
, rXmlEventName
.m_aName
) );
211 // delegate to proper ExportEventHandler
212 m_aHandlerMap
[sType
]->Export(m_rExport
, aEventQName
,
213 rEventValues
, bUseWhitespace
);
217 if ( sType
!= "None" )
219 OSL_FAIL("unknown event type returned by API");
220 // unknown type -> error (ignore)
222 // else: we ignore None fields
227 void XMLEventExport::StartElement(bool bWhitespace
)
231 m_rExport
.IgnorableWhitespace();
233 sal_uInt16 nNamespace
= m_bExtNamespace
? XML_NAMESPACE_OFFICE_EXT
234 : XML_NAMESPACE_OFFICE
;
235 m_rExport
.StartElement( nNamespace
, XML_EVENT_LISTENERS
,
239 void XMLEventExport::EndElement(bool bWhitespace
)
241 sal_uInt16 nNamespace
= m_bExtNamespace
? XML_NAMESPACE_OFFICE_EXT
242 : XML_NAMESPACE_OFFICE
;
243 m_rExport
.EndElement(nNamespace
, XML_EVENT_LISTENERS
, bWhitespace
);
246 m_rExport
.IgnorableWhitespace();
251 // implement aStandardEventTable (defined in xmlevent.hxx)
252 const XMLEventNameTranslation aStandardEventTable
[] =
254 { u
"OnSelect"_ustr
, XML_NAMESPACE_DOM
, u
"select"_ustr
}, // "on-select"
255 { u
"OnInsertStart"_ustr
, XML_NAMESPACE_OFFICE
, u
"insert-start"_ustr
}, // "on-insert-start"
256 { u
"OnInsertDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"insert-done"_ustr
}, // "on-insert-done"
257 { u
"OnMailMerge"_ustr
, XML_NAMESPACE_OFFICE
, u
"mail-merge"_ustr
}, // "on-mail-merge"
258 { u
"OnAlphaCharInput"_ustr
, XML_NAMESPACE_OFFICE
, u
"alpha-char-input"_ustr
}, // "on-alpha-char-input"
259 { u
"OnNonAlphaCharInput"_ustr
, XML_NAMESPACE_OFFICE
, u
"non-alpha-char-input"_ustr
}, // "on-non-alpha-char-input"
260 { u
"OnResize"_ustr
, XML_NAMESPACE_DOM
, u
"resize"_ustr
}, // "on-resize"
261 { u
"OnMove"_ustr
, XML_NAMESPACE_OFFICE
, u
"move"_ustr
}, // "on-move"
262 { u
"OnPageCountChange"_ustr
, XML_NAMESPACE_OFFICE
, u
"page-count-change"_ustr
}, // "on-page-count-change"
263 { u
"OnMouseOver"_ustr
, XML_NAMESPACE_DOM
, u
"mouseover"_ustr
}, // "on-mouse-over"
264 { u
"OnClick"_ustr
, XML_NAMESPACE_DOM
, u
"click"_ustr
}, // "on-click"
265 { u
"OnMouseOut"_ustr
, XML_NAMESPACE_DOM
, u
"mouseout"_ustr
}, // "on-mouse-out"
266 { u
"OnLoadError"_ustr
, XML_NAMESPACE_OFFICE
, u
"load-error"_ustr
}, // "on-load-error"
267 { u
"OnLoadCancel"_ustr
, XML_NAMESPACE_OFFICE
, u
"load-cancel"_ustr
}, // "on-load-cancel"
268 { u
"OnLoadDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"load-done"_ustr
}, // "on-load-done"
269 { u
"OnLoad"_ustr
, XML_NAMESPACE_DOM
, u
"load"_ustr
}, // "on-load"
270 { u
"OnUnload"_ustr
, XML_NAMESPACE_DOM
, u
"unload"_ustr
}, // "on-unload"
271 { u
"OnStartApp"_ustr
, XML_NAMESPACE_OFFICE
, u
"start-app"_ustr
}, // "on-start-app"
272 { u
"OnCloseApp"_ustr
, XML_NAMESPACE_OFFICE
, u
"close-app"_ustr
}, // "on-close-app"
273 { u
"OnNew"_ustr
, XML_NAMESPACE_OFFICE
, u
"new"_ustr
}, // "on-new"
274 { u
"OnSave"_ustr
, XML_NAMESPACE_OFFICE
, u
"save"_ustr
}, // "on-save"
275 { u
"OnSaveAs"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-as"_ustr
}, // "on-save-as"
276 { u
"OnFocus"_ustr
, XML_NAMESPACE_DOM
, u
"DOMFocusIn"_ustr
}, // "on-focus"
277 { u
"OnUnfocus"_ustr
, XML_NAMESPACE_DOM
, u
"DOMFocusOut"_ustr
}, // "on-unfocus"
278 { u
"OnPrint"_ustr
, XML_NAMESPACE_OFFICE
, u
"print"_ustr
}, // "on-print"
279 { u
"OnError"_ustr
, XML_NAMESPACE_DOM
, u
"error"_ustr
}, // "on-error"
280 { u
"OnLoadFinished"_ustr
, XML_NAMESPACE_OFFICE
, u
"load-finished"_ustr
}, // "on-load-finished"
281 { u
"OnSaveFinished"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-finished"_ustr
}, // "on-save-finished"
282 { u
"OnModifyChanged"_ustr
, XML_NAMESPACE_OFFICE
, u
"modify-changed"_ustr
}, // "on-modify-changed"
283 { u
"OnPrepareUnload"_ustr
, XML_NAMESPACE_OFFICE
, u
"prepare-unload"_ustr
}, // "on-prepare-unload"
284 { u
"OnNewMail"_ustr
, XML_NAMESPACE_OFFICE
, u
"new-mail"_ustr
}, // "on-new-mail"
285 { u
"OnToggleFullscreen"_ustr
, XML_NAMESPACE_OFFICE
, u
"toggle-fullscreen"_ustr
}, // "on-toggle-fullscreen"
286 { u
"OnSaveDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-done"_ustr
}, // "on-save-done"
287 { u
"OnSaveAsDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-as-done"_ustr
}, // "on-save-as-done"
288 { u
"OnCopyTo"_ustr
, XML_NAMESPACE_OFFICE
, u
"copy-to"_ustr
},
289 { u
"OnCopyToDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"copy-to-done"_ustr
},
290 { u
"OnViewCreated"_ustr
, XML_NAMESPACE_OFFICE
, u
"view-created"_ustr
},
291 { u
"OnPrepareViewClosing"_ustr
, XML_NAMESPACE_OFFICE
, u
"prepare-view-closing"_ustr
},
292 { u
"OnViewClosed"_ustr
, XML_NAMESPACE_OFFICE
, u
"view-close"_ustr
},
293 { u
"OnVisAreaChanged"_ustr
, XML_NAMESPACE_OFFICE
, u
"visarea-changed"_ustr
}, // "on-visarea-changed"
294 { u
"OnCreate"_ustr
, XML_NAMESPACE_OFFICE
, u
"create"_ustr
},
295 { u
"OnSaveAsFailed"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-as-failed"_ustr
},
296 { u
"OnSaveFailed"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-failed"_ustr
},
297 { u
"OnCopyToFailed"_ustr
, XML_NAMESPACE_OFFICE
, u
"copy-to-failed"_ustr
},
298 { u
"OnTitleChanged"_ustr
, XML_NAMESPACE_OFFICE
, u
"title-changed"_ustr
},
299 { u
"OnModeChanged"_ustr
, XML_NAMESPACE_OFFICE
, u
"mode-changed"_ustr
},
300 { u
"OnSaveTo"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-to"_ustr
},
301 { u
"OnSaveToDone"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-to-done"_ustr
},
302 { u
"OnSaveToFailed"_ustr
, XML_NAMESPACE_OFFICE
, u
"save-to-failed"_ustr
},
303 { u
"OnSubComponentOpened"_ustr
, XML_NAMESPACE_OFFICE
, u
"subcomponent-opened"_ustr
},
304 { u
"OnSubComponentClosed"_ustr
, XML_NAMESPACE_OFFICE
, u
"subcomponent-closed"_ustr
},
305 { u
"OnStorageChanged"_ustr
, XML_NAMESPACE_OFFICE
, u
"storage-changed"_ustr
},
306 { u
"OnMailMergeFinished"_ustr
, XML_NAMESPACE_OFFICE
, u
"mail-merge-finished"_ustr
},
307 { u
"OnFieldMerge"_ustr
, XML_NAMESPACE_OFFICE
, u
"field-merge"_ustr
},
308 { u
"OnFieldMergeFinished"_ustr
, XML_NAMESPACE_OFFICE
, u
"field-merge-finished"_ustr
},
309 { u
"OnLayoutFinished"_ustr
, XML_NAMESPACE_OFFICE
, u
"layout-finished"_ustr
},
310 { u
"OnDoubleClick"_ustr
, XML_NAMESPACE_OFFICE
, u
"dblclick"_ustr
},
311 { u
"OnRightClick"_ustr
, XML_NAMESPACE_OFFICE
, u
"contextmenu"_ustr
},
312 { u
"OnChange"_ustr
, XML_NAMESPACE_OFFICE
, u
"content-changed"_ustr
},
313 { u
"OnCalculate"_ustr
, XML_NAMESPACE_OFFICE
, u
"calculated"_ustr
},
315 { u
""_ustr
, 0, u
""_ustr
}
318 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */