bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / forms / layerexport.cxx
blob634aba470eb6137827521c35979449a749dd5ebe
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 "layerexport.hxx"
21 #include "strings.hxx"
22 #include <xmloff/xmlexp.hxx>
23 #include <xmloff/nmspmap.hxx>
24 #include <xmloff/xmlnmspe.hxx>
25 #include <xmloff/xmluconv.hxx>
26 #include <xmloff/xmlprmap.hxx>
27 #include <xmloff/prhdlfac.hxx>
28 #include "elementexport.hxx"
29 #include <xmloff/families.hxx>
30 #include <xmloff/contextid.hxx>
31 #include <xmloff/controlpropertyhdl.hxx>
32 #include <xmloff/maptype.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <tools/debug.hxx>
35 #include "controlpropertymap.hxx"
36 #include <com/sun/star/container/XIndexAccess.hpp>
37 #include <com/sun/star/form/XFormsSupplier2.hpp>
38 #include <com/sun/star/xforms/XFormsSupplier.hpp>
39 #include <com/sun/star/form/FormComponentType.hpp>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/script/XEventAttacherManager.hpp>
43 #include <com/sun/star/util/NumberFormatsSupplier.hpp>
44 #include "eventexport.hxx"
45 #include <xmloff/XMLEventExport.hxx>
46 #include "formevents.hxx"
47 #include <xmloff/xmlnumfe.hxx>
48 #include <xmloff/xformsexport.hxx>
49 #include <comphelper/processfactory.hxx>
51 #include <com/sun/star/text/XText.hpp>
53 #include <numeric>
55 namespace xmloff
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::awt;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::drawing;
64 using namespace ::com::sun::star::form;
65 using namespace ::com::sun::star::script;
66 using namespace ::com::sun::star::util;
67 using namespace ::com::sun::star::text;
69 typedef ::com::sun::star::xforms::XFormsSupplier XXFormsSupplier;
71 //= OFormLayerXMLExport_Impl
72 const OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix()
74 static const OUString s_sControlNumberStyleNamePrefix("C");
75 return s_sControlNumberStyleNamePrefix;
78 OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext)
79 :m_rContext(_rContext)
80 ,m_pControlNumberStyles(NULL)
82 initializePropertyMaps();
84 // add our style family to the export context's style pool
85 m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory();
86 ::rtl::Reference< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory.get(), true );
87 m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper.get() );
89 // our style family
90 m_rContext.GetAutoStylePool()->AddFamily(
91 XML_STYLE_FAMILY_CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH),
92 m_xStyleExportMapper.get(),
93 OUString( XML_STYLE_FAMILY_CONTROL_PREFIX )
96 // add our event translation table
97 m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation);
99 clear();
102 OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl()
106 bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms)
108 Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY);
109 OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!");
110 if (!xFormsSupp.is())
111 return false;
113 if ( !xFormsSupp->hasForms() )
114 // nothing to do at all
115 return false;
117 _rxForms = Reference< XIndexAccess >(xFormsSupp->getForms(), UNO_QUERY);
118 Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important!
119 OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!");
120 if (!xSI.is())
121 return false;
123 if (!xSI->supportsService("com.sun.star.form.Forms"))
125 OSL_FAIL("OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!");
126 // nothing to do
127 return false;
129 return true;
132 void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn,
133 const Sequence< ScriptEventDescriptor >& _rEvents)
135 // do the exporting
136 OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents);
137 aExportImpl.doExport();
140 void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl,
141 const Sequence< ScriptEventDescriptor >& _rEvents)
143 // the list of the referring controls
144 OUString sReferringControls;
145 MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl);
146 if (aReferring != m_aCurrentPageReferring->second.end())
147 sReferringControls = aReferring->second;
149 // the control id (should already have been created in examineForms)
150 OUString sControlId( getControlId( _rxControl ) );
152 // do the exporting
153 OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents);
154 aExportImpl.doExport();
157 void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps,
158 const Sequence< ScriptEventDescriptor >& _rEvents)
160 OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!");
161 OFormExport aAttributeHandler(*this, _rxProps, _rEvents);
162 aAttributeHandler.doExport();
165 ::rtl::Reference< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper()
167 return m_xStyleExportMapper;
170 SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext()
172 return m_rContext;
175 void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection)
177 // step through all the elements of the collection
178 sal_Int32 nElements = _rxCollection->getCount();
180 Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY);
181 Sequence< ScriptEventDescriptor > aElementEvents;
183 Reference< XPropertySetInfo > xPropsInfo;
184 Reference< XIndexAccess > xCurrentContainer;
185 for (sal_Int32 i=0; i<nElements; ++i)
189 // extract the current element
190 Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY );
191 OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!");
192 if (!xCurrentProps.is())
193 continue;
195 // check if there is a ClassId property on the current element. If so, we assume it to be a control
196 xPropsInfo = xCurrentProps->getPropertySetInfo();
197 OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!");
198 if (!xPropsInfo.is())
199 // without this, a lot of stuff in the export routines may fail
200 continue;
202 // if the element is part of a ignore list, we are not allowed to export it
203 if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) )
204 continue;
206 if (xElementEventManager.is())
207 aElementEvents = xElementEventManager->getScriptEvents(i);
209 if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME))
211 exportGridColumn(xCurrentProps, aElementEvents);
213 else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID))
215 exportControl(xCurrentProps, aElementEvents);
217 else
219 exportForm(xCurrentProps, aElementEvents);
222 catch(Exception&)
224 OSL_FAIL("OFormLayerXMLExport_Impl::exportCollectionElements: caught an exception ... skipping the current element!");
225 continue;
230 OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject )
232 OUString aObjectStyle;
234 MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject );
235 if ( m_aGridColumnStyles.end() != aObjectStylePos )
236 aObjectStyle = aObjectStylePos->second;
237 return aObjectStyle;
240 void OFormLayerXMLExport_Impl::clear()
242 m_aControlIds.clear();
243 m_aReferringControls.clear();
244 m_aCurrentPageIds = m_aControlIds.end();
245 m_aCurrentPageReferring = m_aReferringControls.end();
247 m_aControlNumberFormats.clear();
248 m_aGridColumnStyles.clear();
250 m_aIgnoreList.clear();
253 void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles()
255 if ( m_pControlNumberStyles )
256 m_pControlNumberStyles->Export( true );
259 void OFormLayerXMLExport_Impl::exportAutoStyles()
261 m_rContext.GetAutoStylePool()->exportXML(
262 XML_STYLE_FAMILY_CONTROL_ID,
263 m_rContext.GetDocHandler(),
264 m_rContext.GetMM100UnitConverter(),
265 m_rContext.GetNamespaceMap()
269 void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage)
271 // get the forms collection of the page
272 Reference< XIndexAccess > xCollectionIndex;
273 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
275 return;
278 #if OSL_DEBUG_LEVEL > 0
279 bool bPageIsKnown =
280 #endif
281 implMoveIterators(_rxDrawPage, false);
282 OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!");
284 // export forms collection
285 exportCollectionElements(xCollectionIndex);
288 void OFormLayerXMLExport_Impl::exportXForms() const
290 // export XForms models
291 ::exportXForms( m_rContext );
294 bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage )
296 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
297 DBG_ASSERT( xFormsSupp.is(), "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" );
298 return xFormsSupp.is() && xFormsSupp->hasForms();
301 bool OFormLayerXMLExport_Impl::documentContainsXForms() const
303 Reference< XXFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY );
304 Reference< XNameContainer > xForms;
305 if ( xXFormSupp.is() )
306 xForms = xXFormSupp->getXForms();
307 return xForms.is() && xForms->hasElements();
310 bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, bool _bClear)
312 if (!_rxDrawPage.is())
313 return false;
315 bool bKnownPage = false;
317 // the one for the ids
318 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
319 if (m_aControlIds.end() == m_aCurrentPageIds)
321 m_aControlIds[_rxDrawPage] = MapPropertySet2String();
322 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
324 else
326 bKnownPage = true;
327 if (_bClear && !m_aCurrentPageIds->second.empty() )
328 m_aCurrentPageIds->second.clear();
331 // the one for the ids of the referring controls
332 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
333 if (m_aReferringControls.end() == m_aCurrentPageReferring)
335 m_aReferringControls[_rxDrawPage] = MapPropertySet2String();
336 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
338 else
340 bKnownPage = true;
341 if (_bClear && !m_aCurrentPageReferring->second.empty() )
342 m_aCurrentPageReferring->second.clear();
344 return bKnownPage;
347 bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage)
349 bool bKnownPage = implMoveIterators( _rxDrawPage, false );
350 if ( bKnownPage )
351 return true;
353 // if the page is not yet known, this does not automatically mean that it has
354 // not been examined. Instead, examineForms returns silently and successfully
355 // if a page is a XFormsPageSupplier2, but does not have a forms collection
356 // (This behaviour of examineForms is a performance optimization, to not force
357 // the page to create a forms container just to see that it's empty.)
359 // So, in such a case, seekPage is considered to be successful, too, though the
360 // page was not yet known
361 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
362 if ( xFormsSupp.is() && !xFormsSupp->hasForms() )
363 return true;
365 // anything else means that the page has not been examined before, or it's no
366 // valid form page. Both cases are Bad (TM).
367 return false;
370 OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl)
372 if (m_aCurrentPageIds == m_aControlIds.end())
373 return OUString();
375 OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl),
376 "OFormLayerXMLExport_Impl::getControlId: can not find the control!");
377 return m_aCurrentPageIds->second[_rxControl];
380 OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject )
382 OUString sNumberStyle;
384 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject );
385 if ( -1 != nOwnFormatKey )
386 sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey );
388 return sNumberStyle;
391 OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl )
393 OUString sNumberStyle;
395 MapPropertySet2Int::const_iterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl);
396 if (m_aControlNumberFormats.end() != aControlFormatPos)
398 OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!");
399 sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second);
401 // it's allowed to ask for a control which does not have format information.
402 // (This is for performance reasons)
404 return sNumberStyle;
407 void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage)
409 // get the forms collection of the page
410 Reference< XIndexAccess > xCollectionIndex;
411 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
413 return;
416 // move the iterator which specify the currently handled page
417 #if OSL_DEBUG_LEVEL > 0
418 bool bPageIsKnown =
419 #endif
420 implMoveIterators(_rxDrawPage, true);
421 OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!");
423 ::std::stack< Reference< XIndexAccess > > aContainerHistory;
424 ::std::stack< sal_Int32 > aIndexHistory;
426 Reference< XIndexAccess > xLoop = xCollectionIndex;
427 sal_Int32 nChildPos = 0;
430 if (nChildPos < xLoop->getCount())
432 Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY );
433 OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object");
434 if (!xCurrent.is())
435 continue;
437 if (!checkExamineControl(xCurrent))
439 // step down
440 Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY);
441 OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?");
442 aContainerHistory.push(xLoop);
443 aIndexHistory.push(nChildPos);
445 xLoop = xNextContainer;
446 nChildPos = -1; // will be incremented below
448 ++nChildPos;
450 else
452 // step up
453 while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() )
455 xLoop = aContainerHistory.top();
456 aContainerHistory.pop();
457 nChildPos = aIndexHistory.top();
458 aIndexHistory.pop();
460 ++nChildPos;
462 if (nChildPos >= xLoop->getCount())
463 // exited the loop above because we have no history anymore (0 == aContainerHistory.size()),
464 // and on the current level there are no more children
465 // -> leave
466 break;
469 while (xLoop.is());
472 namespace
474 struct AccumulateSize : public ::std::binary_function< size_t, MapPropertySet2Map::value_type, size_t >
476 size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const
478 return _size + _map.second.size();
482 OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds )
484 static const char sControlIdBase[] = "control";
485 OUString sControlId = sControlIdBase;
487 size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), (size_t)0, AccumulateSize() );
488 sControlId += OUString::number( (sal_Int32)nKnownControlCount + 1 );
490 #ifdef DBG_UTIL
491 // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries
492 // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if
493 // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail.
494 for ( MapPropertySet2Map::const_iterator outer = _rAllPagesControlIds.begin();
495 outer != _rAllPagesControlIds.end();
496 ++outer
498 for ( MapPropertySet2String::const_iterator inner = outer->second.begin();
499 inner != outer->second.end();
500 ++inner
503 OSL_ENSURE( inner->second != sControlId,
504 "lcl_findFreeControlId: auto-generated control ID is already used!" );
506 #endif
507 return sControlId;
511 bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject)
513 Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo();
514 OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info");
516 bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID );
517 if (bIsControl)
519 // generate a new control id
521 // find a free id
522 OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
523 // add it to the map
524 m_aCurrentPageIds->second[_rxObject] = sCurrentId;
526 // check if this control has a "LabelControl" property referring another control
527 if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) )
529 Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY );
530 if (xCurrentReference.is())
532 OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference];
533 if (!sReferencedBy.isEmpty())
534 // it's not the first _rxObject referring to the xCurrentReference
535 // -> separate the id
536 sReferencedBy += ",";
537 sReferencedBy += sCurrentId;
541 // check if the control needs a number format style
542 if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) )
544 examineControlNumberFormat(_rxObject);
547 // check if it's a control providing text
548 Reference< XText > xControlText( _rxObject, UNO_QUERY );
549 if ( xControlText.is() )
551 m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText );
554 // check if it is a grid control - in this case, we need special handling for the columns
555 sal_Int16 nControlType = FormComponentType::CONTROL;
556 _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType;
557 if ( FormComponentType::GRIDCONTROL == nControlType )
559 collectGridColumnStylesAndIds( _rxObject );
563 return bIsControl;
566 void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl )
568 // loop through all columns of the grid
571 Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY );
572 OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" );
573 if ( !xContainer.is() )
574 return;
576 Reference< XPropertySetInfo > xColumnPropertiesMeta;
578 sal_Int32 nCount = xContainer->getCount();
579 for ( sal_Int32 i=0; i<nCount; ++i )
581 Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY );
582 OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" );
583 if ( !xColumnProperties.is() )
584 continue;
586 // generate a new control id
588 // find a free id
589 OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
590 // add it to the map
591 m_aCurrentPageIds->second[ xColumnProperties ] = sCurrentId;
593 // determine a number style, if needed
594 xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo();
595 // get the styles of the column
596 ::std::vector< XMLPropertyState > aPropertyStates = m_xStyleExportMapper->Filter( xColumnProperties );
598 // care for the number format, additionally
599 OUString sColumnNumberStyle;
600 if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) )
601 sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties );
603 if ( !sColumnNumberStyle.isEmpty() )
604 { // the column indeed has a formatting
605 sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE );
606 // TODO: move this to the ctor
607 OSL_ENSURE ( -1 != nStyleMapIndex, "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: could not obtain the index for our context id!");
609 XMLPropertyState aNumberStyleState( nStyleMapIndex, makeAny( sColumnNumberStyle ) );
610 aPropertyStates.push_back( aNumberStyleState );
613 #if OSL_DEBUG_LEVEL > 0
614 ::std::vector< XMLPropertyState >::const_iterator aHaveALook = aPropertyStates.begin();
615 for ( ; aHaveALook != aPropertyStates.end(); ++aHaveALook )
617 (void)aHaveALook;
619 #endif
621 // determine the column style
623 if ( !aPropertyStates.empty() )
624 { // add to the style pool
625 OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XML_STYLE_FAMILY_CONTROL_ID, aPropertyStates );
627 OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ),
628 "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" );
630 m_aGridColumnStyles.insert( MapPropertySet2String::value_type( xColumnProperties, sColumnStyleName ) );
634 catch( const Exception& )
636 DBG_UNHANDLED_EXCEPTION();
640 sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject )
642 // get the format key relative to our own formats supplier
643 sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject );
645 if ( -1 != nOwnFormatKey )
646 // tell the exporter that we used this format
647 getControlNumberStyleExport()->SetUsed( nOwnFormatKey );
649 return nOwnFormatKey;
652 void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl )
654 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl );
656 if ( -1 == nOwnFormatKey )
657 // nothing to do, the number format of this control is void
658 return;
660 // remember the format key for this control (we'll be asked in getControlNumberStyle for this)
661 OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl),
662 "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!");
663 m_aControlNumberFormats[_rxControl] = nOwnFormatKey;
666 sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl)
668 ensureControlNumberStyleExport();
669 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!");
670 // (should have been created in ensureControlNumberStyleExport)
672 sal_Int32 nOwnFormatKey = -1;
674 // the format key (relative to the control's supplier)
675 sal_Int32 nControlFormatKey = -1;
676 Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY);
677 if (aControlFormatKey >>= nControlFormatKey)
679 // the control's number format
680 Reference< XNumberFormatsSupplier > xControlFormatsSupplier;
681 _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier;
682 Reference< XNumberFormats > xControlFormats;
683 if (xControlFormatsSupplier.is())
684 xControlFormats = xControlFormatsSupplier->getNumberFormats();
685 OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!");
687 // obtain the persistent (does not depend on the formats supplier) representation of the control's format
688 Locale aFormatLocale;
689 OUString sFormatDescription;
690 if (xControlFormats.is())
692 Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey);
694 xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale;
695 xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription;
698 // check if our own formats collection already knows the format
699 nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, sal_False);
700 if (-1 == nOwnFormatKey)
701 { // no, we don't
702 // -> create a new format
703 nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale);
705 OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!");
707 else
708 OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!");
710 return nOwnFormatKey;
713 void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport()
715 if (!m_pControlNumberStyles)
717 // create our number formats supplier (if necessary)
718 Reference< XNumberFormatsSupplier > xFormatsSupplier;
720 OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!");
721 // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together
725 // create it for en-US (does not really matter, as we will specify a locale for every
726 // concrete language to use)
727 Locale aLocale ( OUString("en"),
728 OUString("US"),
729 OUString()
731 xFormatsSupplier = NumberFormatsSupplier::createWithLocale( m_rContext.getComponentContext(), aLocale );
732 m_xControlNumberFormats = xFormatsSupplier->getNumberFormats();
734 catch(const Exception&)
738 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!");
740 // create the exporter
741 m_pControlNumberStyles = new SvXMLNumFmtExport(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix());
745 SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport()
747 ensureControlNumberStyleExport();
748 return m_pControlNumberStyles;
751 void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel >& _rxControl )
753 Reference< XPropertySet > xProps( _rxControl, UNO_QUERY );
754 OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" );
755 #if OSL_DEBUG_LEVEL > 0
756 ::std::pair< PropertySetBag::iterator, bool > aPos =
757 #endif
758 m_aIgnoreList.insert( xProps );
759 OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" );
762 } // namespace xmloff
764 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */