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