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 <stdio.h>
21 : #include "layerexport.hxx"
22 : #include "strings.hxx"
23 : #include <xmloff/xmlexp.hxx>
24 : #include <xmloff/nmspmap.hxx>
25 : #include <xmloff/xmlnmspe.hxx>
26 : #include <xmloff/xmluconv.hxx>
27 : #include <xmloff/xmlprmap.hxx>
28 : #include <xmloff/prhdlfac.hxx>
29 : #include "elementexport.hxx"
30 : #include <xmloff/families.hxx>
31 : #include <xmloff/contextid.hxx>
32 : #include <xmloff/controlpropertyhdl.hxx>
33 : #include <tools/diagnose_ex.h>
34 : #include "controlpropertymap.hxx"
35 : #include <com/sun/star/container/XIndexAccess.hpp>
36 : #include <com/sun/star/form/XFormsSupplier2.hpp>
37 : #include <com/sun/star/xforms/XFormsSupplier.hpp>
38 : #include <com/sun/star/form/FormComponentType.hpp>
39 : #include <com/sun/star/lang/XServiceInfo.hpp>
40 : #include <com/sun/star/container/XChild.hpp>
41 : #include <com/sun/star/script/XEventAttacherManager.hpp>
42 : #include <com/sun/star/util/NumberFormatsSupplier.hpp>
43 : #include "eventexport.hxx"
44 : #include <xmloff/XMLEventExport.hxx>
45 : #include "formevents.hxx"
46 : #include <xmloff/xmlnumfe.hxx>
47 : #include <xmloff/xformsexport.hxx>
48 : #include <comphelper/processfactory.hxx>
49 :
50 : #include <com/sun/star/text/XText.hpp>
51 :
52 : #include <numeric>
53 :
54 : namespace xmloff
55 : {
56 :
57 : using namespace ::com::sun::star::uno;
58 : using namespace ::com::sun::star::awt;
59 : using namespace ::com::sun::star::lang;
60 : using namespace ::com::sun::star::beans;
61 : using namespace ::com::sun::star::container;
62 : using namespace ::com::sun::star::drawing;
63 : using namespace ::com::sun::star::form;
64 : using namespace ::com::sun::star::script;
65 : using namespace ::com::sun::star::util;
66 : using namespace ::com::sun::star::text;
67 :
68 : typedef ::com::sun::star::xforms::XFormsSupplier XXFormsSupplier;
69 :
70 : //= OFormLayerXMLExport_Impl
71 0 : const OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix()
72 : {
73 0 : static const OUString s_sControlNumberStyleNamePrefix("C");
74 0 : return s_sControlNumberStyleNamePrefix;
75 : }
76 :
77 0 : OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext)
78 : :m_rContext(_rContext)
79 0 : ,m_pControlNumberStyles(NULL)
80 : {
81 0 : initializePropertyMaps();
82 :
83 : // add our style family to the export context's style pool
84 0 : m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory();
85 0 : ::rtl::Reference< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory.get(), true );
86 0 : m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper.get() );
87 :
88 : // our style family
89 : m_rContext.GetAutoStylePool()->AddFamily(
90 0 : XML_STYLE_FAMILY_CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH),
91 : m_xStyleExportMapper.get(),
92 : OUString( XML_STYLE_FAMILY_CONTROL_PREFIX )
93 0 : );
94 :
95 : // add our event translation table
96 0 : m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation);
97 :
98 0 : clear();
99 0 : }
100 :
101 0 : OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl()
102 : {
103 0 : }
104 :
105 0 : sal_Bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms)
106 : {
107 0 : Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY);
108 : OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!");
109 0 : if (!xFormsSupp.is())
110 0 : return sal_False;
111 :
112 0 : if ( !xFormsSupp->hasForms() )
113 : // nothing to do at all
114 0 : return sal_False;
115 :
116 0 : _rxForms = Reference< XIndexAccess >(xFormsSupp->getForms(), UNO_QUERY);
117 0 : Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important!
118 : OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!");
119 0 : if (!xSI.is())
120 0 : return sal_False;
121 :
122 0 : if (!xSI->supportsService("com.sun.star.form.Forms"))
123 : {
124 : OSL_FAIL("OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!");
125 : // nothing to do
126 0 : return sal_False;
127 : }
128 0 : return sal_True;
129 : }
130 :
131 0 : void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn,
132 : const Sequence< ScriptEventDescriptor >& _rEvents)
133 : {
134 : // do the exporting
135 0 : OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents);
136 0 : aExportImpl.doExport();
137 0 : }
138 :
139 0 : void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl,
140 : const Sequence< ScriptEventDescriptor >& _rEvents)
141 : {
142 : // the list of the referring controls
143 0 : OUString sReferringControls;
144 0 : MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl);
145 0 : if (aReferring != m_aCurrentPageReferring->second.end())
146 0 : sReferringControls = aReferring->second;
147 :
148 : // the control id (should already have been created in examineForms)
149 0 : OUString sControlId( getControlId( _rxControl ) );
150 :
151 : // do the exporting
152 0 : OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents);
153 0 : aExportImpl.doExport();
154 0 : }
155 :
156 0 : void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps,
157 : const Sequence< ScriptEventDescriptor >& _rEvents)
158 : {
159 : OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!");
160 0 : OFormExport aAttributeHandler(*this, _rxProps, _rEvents);
161 0 : aAttributeHandler.doExport();
162 0 : }
163 :
164 0 : ::rtl::Reference< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper()
165 : {
166 0 : return m_xStyleExportMapper;
167 : }
168 :
169 0 : SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext()
170 : {
171 0 : return m_rContext;
172 : }
173 :
174 0 : void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection)
175 : {
176 : // step through all the elements of the collection
177 0 : sal_Int32 nElements = _rxCollection->getCount();
178 :
179 0 : Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY);
180 0 : Sequence< ScriptEventDescriptor > aElementEvents;
181 :
182 0 : Reference< XPropertySetInfo > xPropsInfo;
183 0 : Reference< XIndexAccess > xCurrentContainer;
184 0 : for (sal_Int32 i=0; i<nElements; ++i)
185 : {
186 : try
187 : {
188 : // extract the current element
189 0 : Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY );
190 : OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!");
191 0 : if (!xCurrentProps.is())
192 0 : continue;
193 :
194 : // check if there is a ClassId property on the current element. If so, we assume it to be a control
195 0 : xPropsInfo = xCurrentProps->getPropertySetInfo();
196 : OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!");
197 0 : if (!xPropsInfo.is())
198 : // without this, a lot of stuff in the export routines may fail
199 0 : continue;
200 :
201 : // if the element is part of a ignore list, we are not allowed to export it
202 0 : if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) )
203 0 : continue;
204 :
205 0 : if (xElementEventManager.is())
206 0 : aElementEvents = xElementEventManager->getScriptEvents(i);
207 :
208 0 : if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME))
209 : {
210 0 : exportGridColumn(xCurrentProps, aElementEvents);
211 : }
212 0 : else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID))
213 : {
214 0 : exportControl(xCurrentProps, aElementEvents);
215 : }
216 : else
217 : {
218 0 : exportForm(xCurrentProps, aElementEvents);
219 0 : }
220 : }
221 0 : catch(Exception&)
222 : {
223 : OSL_FAIL("OFormLayerXMLExport_Impl::exportCollectionElements: caught an exception ... skipping the current element!");
224 0 : continue;
225 : }
226 0 : }
227 0 : }
228 :
229 0 : OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject )
230 : {
231 0 : OUString aObjectStyle;
232 :
233 0 : MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject );
234 0 : if ( m_aGridColumnStyles.end() != aObjectStylePos )
235 0 : aObjectStyle = aObjectStylePos->second;
236 0 : return aObjectStyle;
237 : }
238 :
239 0 : void OFormLayerXMLExport_Impl::clear()
240 : {
241 0 : m_aControlIds.clear();
242 0 : m_aReferringControls.clear();
243 0 : m_aCurrentPageIds = m_aControlIds.end();
244 0 : m_aCurrentPageReferring = m_aReferringControls.end();
245 :
246 0 : m_aControlNumberFormats.clear();
247 0 : m_aGridColumnStyles.clear();
248 :
249 0 : m_aIgnoreList.clear();
250 0 : }
251 :
252 0 : void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles()
253 : {
254 0 : if ( m_pControlNumberStyles )
255 0 : m_pControlNumberStyles->Export( true );
256 0 : }
257 :
258 0 : void OFormLayerXMLExport_Impl::exportAutoStyles()
259 : {
260 : m_rContext.GetAutoStylePool()->exportXML(
261 : XML_STYLE_FAMILY_CONTROL_ID,
262 0 : m_rContext.GetDocHandler(),
263 0 : m_rContext.GetMM100UnitConverter(),
264 0 : m_rContext.GetNamespaceMap()
265 0 : );
266 0 : }
267 :
268 0 : void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage)
269 : {
270 : // get the forms collection of the page
271 0 : Reference< XIndexAccess > xCollectionIndex;
272 0 : if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
273 : {
274 0 : return;
275 : }
276 :
277 : #if OSL_DEBUG_LEVEL > 0
278 : sal_Bool bPageIsKnown =
279 : #endif
280 0 : implMoveIterators(_rxDrawPage, sal_False);
281 : OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!");
282 :
283 : // export forms collection
284 0 : exportCollectionElements(xCollectionIndex);
285 : }
286 :
287 0 : void OFormLayerXMLExport_Impl::exportXForms() const
288 : {
289 : // export XForms models
290 0 : ::exportXForms( m_rContext );
291 0 : }
292 :
293 0 : bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage ) const
294 : {
295 0 : Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
296 : DBG_ASSERT( xFormsSupp.is(), "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" );
297 0 : return xFormsSupp.is() && xFormsSupp->hasForms();
298 : }
299 :
300 0 : bool OFormLayerXMLExport_Impl::documentContainsXForms() const
301 : {
302 0 : Reference< XXFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY );
303 0 : Reference< XNameContainer > xForms;
304 0 : if ( xXFormSupp.is() )
305 0 : xForms = xXFormSupp->getXForms();
306 0 : return xForms.is() && xForms->hasElements();
307 : }
308 :
309 0 : sal_Bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, sal_Bool _bClear)
310 : {
311 0 : if (!_rxDrawPage.is())
312 0 : return false;
313 :
314 0 : sal_Bool bKnownPage = sal_False;
315 :
316 : // the one for the ids
317 0 : m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
318 0 : if (m_aControlIds.end() == m_aCurrentPageIds)
319 : {
320 0 : m_aControlIds[_rxDrawPage] = MapPropertySet2String();
321 0 : m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
322 : }
323 : else
324 : {
325 0 : bKnownPage = sal_True;
326 0 : if (_bClear && !m_aCurrentPageIds->second.empty() )
327 0 : m_aCurrentPageIds->second.clear();
328 : }
329 :
330 : // the one for the ids of the referring controls
331 0 : m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
332 0 : if (m_aReferringControls.end() == m_aCurrentPageReferring)
333 : {
334 0 : m_aReferringControls[_rxDrawPage] = MapPropertySet2String();
335 0 : m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
336 : }
337 : else
338 : {
339 0 : bKnownPage = sal_True;
340 0 : if (_bClear && !m_aCurrentPageReferring->second.empty() )
341 0 : m_aCurrentPageReferring->second.clear();
342 : }
343 0 : return bKnownPage;
344 : }
345 :
346 0 : sal_Bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage)
347 : {
348 0 : sal_Bool bKnownPage = implMoveIterators( _rxDrawPage, sal_False );
349 0 : if ( bKnownPage )
350 0 : return sal_True;
351 :
352 : // if the page is not yet known, this does not automatically mean that it has
353 : // not been examined. Instead, examineForms returns silently and successfully
354 : // if a page is a XFormsPageSupplier2, but does not have a forms collection
355 : // (This behaviour of examineForms is a performance optimization, to not force
356 : // the page to create a forms container just to see that it's empty.)
357 :
358 : // So, in such a case, seekPage is considered to be successful, too, though the
359 : // page was not yet known
360 0 : Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
361 0 : if ( xFormsSupp.is() && !xFormsSupp->hasForms() )
362 0 : return sal_True;
363 :
364 : // anything else means that the page has not been examined before, or it's no
365 : // valid form page. Both cases are Bad (TM).
366 0 : return sal_False;
367 : }
368 :
369 0 : OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl)
370 : {
371 0 : if (m_aCurrentPageIds == m_aControlIds.end())
372 0 : return OUString();
373 :
374 : OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl),
375 : "OFormLayerXMLExport_Impl::getControlId: can not find the control!");
376 0 : return m_aCurrentPageIds->second[_rxControl];
377 : }
378 :
379 0 : OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject )
380 : {
381 0 : OUString sNumberStyle;
382 :
383 0 : sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject );
384 0 : if ( -1 != nOwnFormatKey )
385 0 : sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey );
386 :
387 0 : return sNumberStyle;
388 : }
389 :
390 0 : OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl )
391 : {
392 0 : OUString sNumberStyle;
393 :
394 0 : MapPropertySet2Int::const_iterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl);
395 0 : if (m_aControlNumberFormats.end() != aControlFormatPos)
396 : {
397 : OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!");
398 0 : sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second);
399 : }
400 : // it's allowed to ask for a control which does not have format information.
401 : // (This is for performance reasons)
402 :
403 0 : return sNumberStyle;
404 : }
405 :
406 0 : void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage)
407 : {
408 : // get the forms collection of the page
409 0 : Reference< XIndexAccess > xCollectionIndex;
410 0 : if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
411 : {
412 0 : return;
413 : }
414 :
415 : // move the iterator which specify the currently handled page
416 : #if OSL_DEBUG_LEVEL > 0
417 : sal_Bool bPageIsKnown =
418 : #endif
419 0 : implMoveIterators(_rxDrawPage, sal_True);
420 : OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!");
421 :
422 0 : ::std::stack< Reference< XIndexAccess > > aContainerHistory;
423 0 : ::std::stack< sal_Int32 > aIndexHistory;
424 :
425 0 : Reference< XIndexAccess > xLoop = xCollectionIndex;
426 0 : sal_Int32 nChildPos = 0;
427 0 : do
428 : {
429 0 : if (nChildPos < xLoop->getCount())
430 : {
431 0 : Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY );
432 : OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object");
433 0 : if (!xCurrent.is())
434 0 : continue;
435 :
436 0 : if (!checkExamineControl(xCurrent))
437 : {
438 : // step down
439 0 : Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY);
440 : OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?");
441 0 : aContainerHistory.push(xLoop);
442 0 : aIndexHistory.push(nChildPos);
443 :
444 0 : xLoop = xNextContainer;
445 0 : nChildPos = -1; // will be incremented below
446 : }
447 0 : ++nChildPos;
448 : }
449 : else
450 : {
451 : // step up
452 0 : while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() )
453 : {
454 0 : xLoop = aContainerHistory.top();
455 0 : aContainerHistory.pop();
456 0 : nChildPos = aIndexHistory.top();
457 0 : aIndexHistory.pop();
458 :
459 0 : ++nChildPos;
460 : }
461 0 : if (nChildPos >= xLoop->getCount())
462 : // exited the loop above because we have no history anymore (0 == aContainerHistory.size()),
463 : // and on the current level there are no more children
464 : // -> leave
465 0 : break;
466 : }
467 : }
468 0 : while (xLoop.is());
469 : }
470 :
471 : namespace
472 : {
473 : struct AccumulateSize : public ::std::binary_function< size_t, MapPropertySet2Map::value_type, size_t >
474 : {
475 0 : size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const
476 : {
477 0 : return _size + _map.second.size();
478 : }
479 : };
480 :
481 0 : OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds )
482 : {
483 0 : static const OUString sControlIdBase( "control" );
484 0 : OUString sControlId = sControlIdBase;
485 :
486 0 : size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), (size_t)0, AccumulateSize() );
487 0 : sControlId += OUString::number( (sal_Int32)nKnownControlCount + 1 );
488 :
489 : #ifdef DBG_UTIL
490 : // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries
491 : // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if
492 : // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail.
493 : for ( MapPropertySet2Map::const_iterator outer = _rAllPagesControlIds.begin();
494 : outer != _rAllPagesControlIds.end();
495 : ++outer
496 : )
497 : for ( MapPropertySet2String::const_iterator inner = outer->second.begin();
498 : inner != outer->second.end();
499 : ++inner
500 : )
501 : {
502 : OSL_ENSURE( inner->second != sControlId,
503 : "lcl_findFreeControlId: auto-generated control ID is already used!" );
504 : }
505 : #endif
506 0 : return sControlId;
507 : }
508 : }
509 :
510 0 : sal_Bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject)
511 : {
512 0 : Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo();
513 : OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info");
514 :
515 0 : sal_Bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID );
516 0 : if (bIsControl)
517 : {
518 : // generate a new control id
519 :
520 : // find a free id
521 0 : OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
522 : // add it to the map
523 0 : m_aCurrentPageIds->second[_rxObject] = sCurrentId;
524 :
525 : // check if this control has a "LabelControl" property referring another control
526 0 : if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) )
527 : {
528 0 : Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY );
529 0 : if (xCurrentReference.is())
530 : {
531 0 : OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference];
532 0 : if (!sReferencedBy.isEmpty())
533 : // it's not the first _rxObject referring to the xCurrentReference
534 : // -> separate the id
535 0 : sReferencedBy += ",";
536 0 : sReferencedBy += sCurrentId;
537 0 : }
538 : }
539 :
540 : // check if the control needs a number format style
541 0 : if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) )
542 : {
543 0 : examineControlNumberFormat(_rxObject);
544 : }
545 :
546 : // check if it's a control providing text
547 0 : Reference< XText > xControlText( _rxObject, UNO_QUERY );
548 0 : if ( xControlText.is() )
549 : {
550 0 : m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText );
551 : }
552 :
553 : // check if it is a grid control - in this case, we need special handling for the columns
554 0 : sal_Int16 nControlType = FormComponentType::CONTROL;
555 0 : _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType;
556 0 : if ( FormComponentType::GRIDCONTROL == nControlType )
557 : {
558 0 : collectGridColumnStylesAndIds( _rxObject );
559 0 : }
560 : }
561 :
562 0 : return bIsControl;
563 : }
564 :
565 0 : void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl )
566 : {
567 : // loop through all columns of the grid
568 : try
569 : {
570 0 : Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY );
571 : OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" );
572 0 : if ( !xContainer.is() )
573 0 : return;
574 :
575 0 : Reference< XPropertySetInfo > xColumnPropertiesMeta;
576 :
577 0 : sal_Int32 nCount = xContainer->getCount();
578 0 : for ( sal_Int32 i=0; i<nCount; ++i )
579 : {
580 0 : Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY );
581 : OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" );
582 0 : if ( !xColumnProperties.is() )
583 0 : continue;
584 :
585 : // generate a new control id
586 :
587 : // find a free id
588 0 : OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
589 : // add it to the map
590 0 : m_aCurrentPageIds->second[ xColumnProperties ] = sCurrentId;
591 :
592 : // determine a number style, if needed
593 0 : xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo();
594 : // get the styles of the column
595 0 : ::std::vector< XMLPropertyState > aPropertyStates = m_xStyleExportMapper->Filter( xColumnProperties );
596 :
597 : // care for the number format, additionally
598 0 : OUString sColumnNumberStyle;
599 0 : if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) )
600 0 : sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties );
601 :
602 0 : if ( !sColumnNumberStyle.isEmpty() )
603 : { // the column indeed has a formatting
604 0 : sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE );
605 : // TODO: move this to the ctor
606 : OSL_ENSURE ( -1 != nStyleMapIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!");
607 :
608 0 : XMLPropertyState aNumberStyleState( nStyleMapIndex, makeAny( sColumnNumberStyle ) );
609 0 : aPropertyStates.push_back( aNumberStyleState );
610 : }
611 :
612 : #if OSL_DEBUG_LEVEL > 0
613 : ::std::vector< XMLPropertyState >::const_iterator aHaveALook = aPropertyStates.begin();
614 : for ( ; aHaveALook != aPropertyStates.end(); ++aHaveALook )
615 : {
616 : (void)aHaveALook;
617 : }
618 : #endif
619 :
620 : // determine the column style
621 :
622 0 : if ( !aPropertyStates.empty() )
623 : { // add to the style pool
624 0 : OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XML_STYLE_FAMILY_CONTROL_ID, aPropertyStates );
625 :
626 : OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ),
627 : "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" );
628 :
629 0 : m_aGridColumnStyles.insert( MapPropertySet2String::value_type( xColumnProperties, sColumnStyleName ) );
630 : }
631 0 : }
632 : }
633 0 : catch( const Exception& )
634 : {
635 : DBG_UNHANDLED_EXCEPTION();
636 : }
637 : }
638 :
639 0 : sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject )
640 : {
641 : // get the format key relative to our own formats supplier
642 0 : sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject );
643 :
644 0 : if ( -1 != nOwnFormatKey )
645 : // tell the exporter that we used this format
646 0 : getControlNumberStyleExport()->SetUsed( nOwnFormatKey );
647 :
648 0 : return nOwnFormatKey;
649 : }
650 :
651 0 : void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl )
652 : {
653 0 : sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl );
654 :
655 0 : if ( -1 == nOwnFormatKey )
656 : // nothing to do, the number format of this control is void
657 0 : return;
658 :
659 : // remember the format key for this control (we'll be asked in getControlNumberStyle for this)
660 : OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl),
661 : "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!");
662 0 : m_aControlNumberFormats[_rxControl] = nOwnFormatKey;
663 : }
664 :
665 0 : sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl)
666 : {
667 0 : ensureControlNumberStyleExport();
668 : OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!");
669 : // (should have been created in ensureControlNumberStyleExport)
670 :
671 0 : sal_Int32 nOwnFormatKey = -1;
672 :
673 : // the format key (relative to the control's supplier)
674 0 : sal_Int32 nControlFormatKey = -1;
675 0 : Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY);
676 0 : if (aControlFormatKey >>= nControlFormatKey)
677 : {
678 : // the control's number format
679 0 : Reference< XNumberFormatsSupplier > xControlFormatsSupplier;
680 0 : _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier;
681 0 : Reference< XNumberFormats > xControlFormats;
682 0 : if (xControlFormatsSupplier.is())
683 0 : xControlFormats = xControlFormatsSupplier->getNumberFormats();
684 : OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!");
685 :
686 : // obtain the persistent (does not depend on the formats supplier) representation of the control's format
687 0 : Locale aFormatLocale;
688 0 : OUString sFormatDescription;
689 0 : if (xControlFormats.is())
690 : {
691 0 : Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey);
692 :
693 0 : xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale;
694 0 : xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription;
695 : }
696 :
697 : // check if our own formats collection already knows the format
698 0 : nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, sal_False);
699 0 : if (-1 == nOwnFormatKey)
700 : { // no, we don't
701 : // -> create a new format
702 0 : nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale);
703 : }
704 0 : OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!");
705 : }
706 : else
707 : OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!");
708 :
709 0 : return nOwnFormatKey;
710 : }
711 :
712 0 : void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport()
713 : {
714 0 : if (!m_pControlNumberStyles)
715 : {
716 : // create our number formats supplier (if necessary)
717 0 : Reference< XNumberFormatsSupplier > xFormatsSupplier;
718 :
719 : OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!");
720 : // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together
721 :
722 : try
723 : {
724 : // create it for en-US (does not really matter, as we will specify a locale for every
725 : // concrete language to use)
726 : Locale aLocale ( OUString("en"),
727 : OUString("US"),
728 : OUString()
729 0 : );
730 0 : xFormatsSupplier = NumberFormatsSupplier::createWithLocale( m_rContext.getComponentContext(), aLocale );
731 0 : m_xControlNumberFormats = xFormatsSupplier->getNumberFormats();
732 : }
733 0 : catch(const Exception&)
734 : {
735 : }
736 :
737 : OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!");
738 :
739 : // create the exporter
740 0 : m_pControlNumberStyles = new SvXMLNumFmtExport(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix());
741 : }
742 0 : }
743 :
744 0 : SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport()
745 : {
746 0 : ensureControlNumberStyleExport();
747 0 : return m_pControlNumberStyles;
748 : }
749 :
750 0 : void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel > _rxControl )
751 : {
752 0 : Reference< XPropertySet > xProps( _rxControl, UNO_QUERY );
753 : OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" );
754 : #if OSL_DEBUG_LEVEL > 0
755 : ::std::pair< PropertySetBag::iterator, bool > aPos =
756 : #endif
757 0 : m_aIgnoreList.insert( xProps );
758 0 : OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" );
759 0 : }
760 :
761 : } // namespace xmloff
762 :
763 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|