Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <xmloff/XMLEventExport.hxx>
21 :
22 : #include <com/sun/star/beans/PropertyValue.hpp>
23 :
24 : #include <com/sun/star/document/XEventsSupplier.hpp>
25 :
26 : #include <com/sun/star/container/XNameReplace.hpp>
27 : #include <tools/debug.hxx>
28 : #include <xmloff/xmlexp.hxx>
29 : #include <xmloff/xmltoken.hxx>
30 : #include "xmloff/xmlnmspe.hxx"
31 : #include <xmloff/nmspmap.hxx>
32 :
33 :
34 : using namespace ::com::sun::star::uno;
35 :
36 : using std::map;
37 : using ::rtl::OUString;
38 : using ::com::sun::star::beans::PropertyValue;
39 : using ::com::sun::star::document::XEventsSupplier;
40 : using ::com::sun::star::container::XNameReplace;
41 : using ::com::sun::star::container::XNameAccess;
42 : using ::xmloff::token::GetXMLToken;
43 : using ::xmloff::token::XML_EVENT_LISTENERS;
44 :
45 :
46 8 : XMLEventExport::XMLEventExport(SvXMLExport& rExp,
47 : const XMLEventNameTranslation* pTranslationTable) :
48 : sEventType(RTL_CONSTASCII_USTRINGPARAM("EventType")),
49 : rExport(rExp),
50 8 : bExtNamespace(false)
51 : {
52 8 : AddTranslationTable(pTranslationTable);
53 8 : }
54 :
55 16 : XMLEventExport::~XMLEventExport()
56 : {
57 : // delete all handlers
58 8 : HandlerMap::iterator aEnd = aHandlerMap.end();
59 24 : for( HandlerMap::iterator aIter =
60 8 : aHandlerMap.begin();
61 : aIter != aEnd;
62 : ++aIter )
63 : {
64 16 : delete aIter->second;
65 : }
66 8 : aHandlerMap.clear();
67 8 : }
68 :
69 16 : void XMLEventExport::AddHandler( const OUString& rName,
70 : XMLEventExportHandler* pHandler )
71 : {
72 : DBG_ASSERT(pHandler != NULL, "Need EventExportHandler");
73 16 : if (pHandler != NULL)
74 : {
75 16 : aHandlerMap[rName] = pHandler;
76 : }
77 16 : }
78 :
79 20 : void XMLEventExport::AddTranslationTable(
80 : const XMLEventNameTranslation* pTransTable )
81 : {
82 20 : if (NULL != pTransTable)
83 : {
84 : // put translation table into map
85 624 : for(const XMLEventNameTranslation* pTrans = pTransTable;
86 : pTrans->sAPIName != NULL;
87 : pTrans++)
88 : {
89 1224 : aNameTranslationMap[OUString::createFromAscii(pTrans->sAPIName)] =
90 1836 : XMLEventName(pTrans->nPrefix, pTrans->sXMLName);
91 : }
92 : }
93 : // else? ignore!
94 20 : }
95 :
96 36 : void XMLEventExport::Export( Reference<XEventsSupplier> & rSupplier,
97 : sal_Bool bWhitespace)
98 : {
99 36 : if (rSupplier.is())
100 : {
101 4 : Reference<XNameAccess> xAccess(rSupplier->getEvents(), UNO_QUERY);
102 4 : Export(xAccess, bWhitespace);
103 : }
104 : // else: no supplier, no export -> ignore!
105 36 : }
106 :
107 0 : void XMLEventExport::Export( Reference<XNameReplace> & rReplace,
108 : sal_Bool bWhitespace)
109 : {
110 0 : Reference<XNameAccess> xAccess(rReplace, UNO_QUERY);
111 0 : Export(xAccess, bWhitespace);
112 0 : }
113 :
114 4 : void XMLEventExport::Export( Reference<XNameAccess> & rAccess,
115 : sal_Bool bWhitespace)
116 : {
117 : // early out if we don't actually get any events
118 4 : if (!rAccess.is())
119 : {
120 4 : return;
121 : }
122 :
123 : // have we already processed an element?
124 4 : sal_Bool bStarted = sal_False;
125 :
126 : // iterate over all event types
127 4 : Sequence<OUString> aNames = rAccess->getElementNames();
128 4 : sal_Int32 nCount = aNames.getLength();
129 128 : for(sal_Int32 i = 0; i < nCount; i++)
130 : {
131 : // translate name
132 124 : NameMap::iterator aIter = aNameTranslationMap.find(aNames[i]);
133 124 : if (aIter != aNameTranslationMap.end())
134 : {
135 124 : const XMLEventName& rXmlName = aIter->second;
136 :
137 : // get PropertyValues for this event
138 124 : Any aAny = rAccess->getByName( aNames[i] );
139 124 : Sequence<PropertyValue> aValues;
140 124 : aAny >>= aValues;
141 :
142 : // now export the current event
143 124 : ExportEvent( aValues, rXmlName, bWhitespace, bStarted );
144 : }
145 : #ifdef DBG_UTIL
146 : else
147 : {
148 : // don't proceed further
149 : ::rtl::OString aStr("Unknown event name:" );
150 : aStr += ::rtl::OUStringToOString( aNames[i], RTL_TEXTENCODING_UTF8 );
151 : OSL_FAIL( aStr.getStr() );
152 : }
153 : #endif
154 : }
155 :
156 : // close <script:events> element (if it was opened before)
157 4 : if (bStarted)
158 : {
159 0 : EndElement(bWhitespace);
160 4 : }
161 : }
162 :
163 0 : void XMLEventExport::ExportExt( Reference<XNameAccess> & rAccess,
164 : sal_Bool bWhitespace )
165 : {
166 : // set bExtNamespace flag to use XML_NAMESPACE_OFFICE_EXT namespace
167 : // for events element (not for child elements)
168 0 : bExtNamespace = true;
169 0 : Export(rAccess, bWhitespace);
170 0 : bExtNamespace = false; // reset for future Export calls
171 0 : }
172 :
173 : /// export a singular event and wirte <office:events> container
174 0 : void XMLEventExport::ExportSingleEvent(
175 : Sequence<PropertyValue>& rEventValues,
176 : const OUString& rApiEventName,
177 : sal_Bool bUseWhitespace )
178 : {
179 : // translate the name
180 0 : NameMap::iterator aIter = aNameTranslationMap.find(rApiEventName);
181 0 : if (aIter != aNameTranslationMap.end())
182 : {
183 0 : const XMLEventName& rXmlName = aIter->second;
184 :
185 : // export the event ...
186 0 : sal_Bool bStarted = sal_False;
187 0 : ExportEvent( rEventValues, rXmlName, bUseWhitespace, bStarted );
188 :
189 : // ... and close the container element (if necessary)
190 0 : if (bStarted)
191 : {
192 0 : EndElement(bUseWhitespace);
193 : }
194 : }
195 : #ifdef DBG_UTIL
196 : else
197 : {
198 : // don't proceed further
199 : ::rtl::OString aStr("Unknown event name:" );
200 : aStr += ::rtl::OUStringToOString( rApiEventName, RTL_TEXTENCODING_UTF8 );
201 : OSL_FAIL( aStr.getStr() );
202 : }
203 : #endif
204 0 : }
205 :
206 :
207 : /// export a single event
208 124 : void XMLEventExport::ExportEvent(
209 : Sequence<PropertyValue>& rEventValues,
210 : const XMLEventName& rXmlEventName,
211 : sal_Bool bUseWhitespace,
212 : sal_Bool& rExported )
213 : {
214 : // search for EventType value and then delegate to EventHandler
215 124 : sal_Int32 nValues = rEventValues.getLength();
216 124 : const PropertyValue* pValues = rEventValues.getConstArray();
217 :
218 124 : for(sal_Int32 nVal = 0; nVal < nValues; nVal++)
219 : {
220 0 : if (sEventType.equals(pValues[nVal].Name))
221 : {
222 : // found! Now find handler and delegate
223 0 : OUString sType;
224 0 : pValues[nVal].Value >>= sType;
225 :
226 0 : if (aHandlerMap.count(sType))
227 : {
228 0 : if (! rExported)
229 : {
230 : // OK, we have't yet exported the enclosing
231 : // element. So we do that now.
232 0 : rExported = sal_True;
233 0 : StartElement(bUseWhitespace);
234 : }
235 :
236 : OUString aEventQName(
237 0 : rExport.GetNamespaceMap().GetQNameByKey(
238 0 : rXmlEventName.m_nPrefix, rXmlEventName.m_aName ) );
239 :
240 : // delegate to proper ExportEventHandler
241 0 : aHandlerMap[sType]->Export(rExport, aEventQName,
242 0 : rEventValues, bUseWhitespace);
243 : }
244 : else
245 : {
246 0 : if (! sType.equalsAsciiL("None", sizeof("None")-1))
247 : {
248 : OSL_FAIL("unknown event type returned by API");
249 : // unknown type -> error (ignore)
250 : }
251 : // else: we ignore None fields
252 : }
253 :
254 : // early out: we don't need to look for another type
255 0 : break;
256 : }
257 : // else: we only care for EventType -> ignore
258 : }
259 124 : }
260 :
261 :
262 0 : void XMLEventExport::StartElement(sal_Bool bWhitespace)
263 : {
264 0 : if (bWhitespace)
265 : {
266 0 : rExport.IgnorableWhitespace();
267 : }
268 : sal_uInt16 nNamespace = bExtNamespace ? XML_NAMESPACE_OFFICE_EXT
269 0 : : XML_NAMESPACE_OFFICE;
270 : rExport.StartElement( nNamespace, XML_EVENT_LISTENERS,
271 0 : bWhitespace);
272 0 : }
273 :
274 0 : void XMLEventExport::EndElement(sal_Bool bWhitespace)
275 : {
276 : sal_uInt16 nNamespace = bExtNamespace ? XML_NAMESPACE_OFFICE_EXT
277 0 : : XML_NAMESPACE_OFFICE;
278 0 : rExport.EndElement(nNamespace, XML_EVENT_LISTENERS, bWhitespace);
279 0 : if (bWhitespace)
280 : {
281 0 : rExport.IgnorableWhitespace();
282 : }
283 0 : }
284 :
285 :
286 : // implement aStandardEventTable (defined in xmlevent.hxx)
287 : const XMLEventNameTranslation aStandardEventTable[] =
288 : {
289 : { "OnSelect", XML_NAMESPACE_DOM, "select" }, // "on-select"
290 : { "OnInsertStart", XML_NAMESPACE_OFFICE, "insert-start" }, // "on-insert-start"
291 : { "OnInsertDone", XML_NAMESPACE_OFFICE, "insert-done" }, // "on-insert-done"
292 : { "OnMailMerge", XML_NAMESPACE_OFFICE, "mail-merge" }, // "on-mail-merge"
293 : { "OnAlphaCharInput", XML_NAMESPACE_OFFICE, "alpha-char-input" }, // "on-alpha-char-input"
294 : { "OnNonAlphaCharInput", XML_NAMESPACE_OFFICE, "non-alpha-char-input" }, // "on-non-alpha-char-input"
295 : { "OnResize", XML_NAMESPACE_DOM, "resize" }, // "on-resize"
296 : { "OnMove", XML_NAMESPACE_OFFICE, "move" }, // "on-move"
297 : { "OnPageCountChange", XML_NAMESPACE_OFFICE, "page-count-change" }, // "on-page-count-change"
298 : { "OnMouseOver", XML_NAMESPACE_DOM, "mouseover" }, // "on-mouse-over"
299 : { "OnClick", XML_NAMESPACE_DOM, "click" }, // "on-click"
300 : { "OnMouseOut", XML_NAMESPACE_DOM, "mouseout" }, // "on-mouse-out"
301 : { "OnLoadError", XML_NAMESPACE_OFFICE, "load-error" }, // "on-load-error"
302 : { "OnLoadCancel", XML_NAMESPACE_OFFICE, "load-cancel" }, // "on-load-cancel"
303 : { "OnLoadDone", XML_NAMESPACE_OFFICE, "load-done" }, // "on-load-done"
304 : { "OnLoad", XML_NAMESPACE_DOM, "load" }, // "on-load"
305 : { "OnUnload", XML_NAMESPACE_DOM, "unload" }, // "on-unload"
306 : { "OnStartApp", XML_NAMESPACE_OFFICE, "start-app" }, // "on-start-app"
307 : { "OnCloseApp", XML_NAMESPACE_OFFICE, "close-app" }, // "on-close-app"
308 : { "OnNew", XML_NAMESPACE_OFFICE, "new" }, // "on-new"
309 : { "OnSave", XML_NAMESPACE_OFFICE, "save" }, // "on-save"
310 : { "OnSaveAs", XML_NAMESPACE_OFFICE, "save-as" }, // "on-save-as"
311 : { "OnFocus", XML_NAMESPACE_DOM, "DOMFocusIn" }, // "on-focus"
312 : { "OnUnfocus", XML_NAMESPACE_DOM, "DOMFocusOut" }, // "on-unfocus"
313 : { "OnPrint", XML_NAMESPACE_OFFICE, "print" }, // "on-print"
314 : { "OnError", XML_NAMESPACE_DOM, "error" }, // "on-error"
315 : { "OnLoadFinished", XML_NAMESPACE_OFFICE, "load-finished" }, // "on-load-finished"
316 : { "OnSaveFinished", XML_NAMESPACE_OFFICE, "save-finished" }, // "on-save-finished"
317 : { "OnModifyChanged", XML_NAMESPACE_OFFICE, "modify-changed" }, // "on-modify-changed"
318 : { "OnPrepareUnload", XML_NAMESPACE_OFFICE, "prepare-unload" }, // "on-prepare-unload"
319 : { "OnNewMail", XML_NAMESPACE_OFFICE, "new-mail" }, // "on-new-mail"
320 : { "OnToggleFullscreen", XML_NAMESPACE_OFFICE, "toggle-fullscreen" }, // "on-toggle-fullscreen"
321 : { "OnSaveDone", XML_NAMESPACE_OFFICE, "save-done" }, // "on-save-done"
322 : { "OnSaveAsDone", XML_NAMESPACE_OFFICE, "save-as-done" }, // "on-save-as-done"
323 : { "OnCopyTo", XML_NAMESPACE_OFFICE, "copy-to" },
324 : { "OnCopyToDone", XML_NAMESPACE_OFFICE, "copy-to-done" },
325 : { "OnViewCreated", XML_NAMESPACE_OFFICE, "view-created" },
326 : { "OnPrepareViewClosing", XML_NAMESPACE_OFFICE, "prepare-view-closing" },
327 : { "OnViewClosed", XML_NAMESPACE_OFFICE, "view-close" },
328 : { "OnVisAreaChanged", XML_NAMESPACE_OFFICE, "visarea-changed" }, // "on-visarea-changed"
329 : { "OnCreate", XML_NAMESPACE_OFFICE, "create" },
330 : { "OnSaveAsFailed", XML_NAMESPACE_OFFICE, "save-as-failed" },
331 : { "OnSaveFailed", XML_NAMESPACE_OFFICE, "save-failed" },
332 : { "OnCopyToFailed", XML_NAMESPACE_OFFICE, "copy-to-failed" },
333 : { "OnTitleChanged", XML_NAMESPACE_OFFICE, "title-changed" },
334 : { "OnModeChanged", XML_NAMESPACE_OFFICE, "mode-changed" },
335 : { "OnSaveTo", XML_NAMESPACE_OFFICE, "save-to" },
336 : { "OnSaveToDone", XML_NAMESPACE_OFFICE, "save-to-done" },
337 : { "OnSaveToFailed", XML_NAMESPACE_OFFICE, "save-to-failed" },
338 : { "OnSubComponentOpened", XML_NAMESPACE_OFFICE, "subcomponent-opened" },
339 : { "OnSubComponentClosed", XML_NAMESPACE_OFFICE, "subcomponent-closed" },
340 : { "OnStorageChanged", XML_NAMESPACE_OFFICE, "storage-changed" },
341 : { "OnMailMergeFinished", XML_NAMESPACE_OFFICE, "mail-merge-finished" },
342 : { "OnFieldMerge", XML_NAMESPACE_OFFICE, "field-merge" },
343 : { "OnFieldMergeFinished", XML_NAMESPACE_OFFICE, "field-merge-finished" },
344 : { "OnLayoutFinished", XML_NAMESPACE_OFFICE, "layout-finished" },
345 : { "OnDoubleClick", XML_NAMESPACE_OFFICE, "dblclick" },
346 : { "OnRightClick", XML_NAMESPACE_OFFICE, "contextmenu" },
347 : { "OnChange", XML_NAMESPACE_OFFICE, "content-changed" },
348 : { "OnCalculate", XML_NAMESPACE_OFFICE, "calculated" },
349 :
350 : { NULL, 0, 0 }
351 : };
352 :
353 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|