tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / xmloff / source / forms / layerexport.cxx
bloba5c604ca65f08186f3addb508c8db7c14ac23788
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/xmlprmap.hxx>
24 #include <xmloff/prhdlfac.hxx>
25 #include "elementexport.hxx"
26 #include <xmloff/families.hxx>
27 #include <xmloff/contextid.hxx>
28 #include <xmloff/controlpropertyhdl.hxx>
29 #include <xmloff/maptype.hxx>
30 #include <sal/log.hxx>
31 #include <comphelper/diagnose_ex.hxx>
32 #include "controlpropertymap.hxx"
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/form/XFormsSupplier2.hpp>
35 #include <com/sun/star/frame/XModel.hpp>
36 #include <com/sun/star/xforms/XFormsSupplier.hpp>
37 #include <com/sun/star/form/FormComponentType.hpp>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/script/XEventAttacherManager.hpp>
40 #include <com/sun/star/util/NumberFormatsSupplier.hpp>
41 #include <xmloff/XMLEventExport.hxx>
42 #include "formevents.hxx"
43 #include <xmloff/xmlnumfe.hxx>
44 #include <xmloff/xformsexport.hxx>
46 #include <com/sun/star/text/XText.hpp>
48 #include <stack>
49 #include <numeric>
51 namespace xmloff
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::awt;
56 using namespace ::com::sun::star::lang;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::container;
59 using namespace ::com::sun::star::drawing;
60 using namespace ::com::sun::star::form;
61 using namespace ::com::sun::star::script;
62 using namespace ::com::sun::star::util;
63 using namespace ::com::sun::star::text;
65 //= OFormLayerXMLExport_Impl
66 const OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix()
68 static constexpr OUString s_sControlNumberStyleNamePrefix(u"C"_ustr);
69 return s_sControlNumberStyleNamePrefix;
72 OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext)
73 :m_rContext(_rContext)
75 initializePropertyMaps();
77 // add our style family to the export context's style pool
78 m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory();
79 ::rtl::Reference< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory, true );
80 m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper );
82 // our style family
83 m_rContext.GetAutoStylePool()->AddFamily(
84 XmlStyleFamily::CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH),
85 m_xStyleExportMapper.get(),
86 XML_STYLE_FAMILY_CONTROL_PREFIX
89 // add our event translation table
90 m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation);
92 clear();
95 OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl()
99 bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms)
101 Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY);
102 OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!");
103 if (!xFormsSupp.is())
104 return false;
106 if ( !xFormsSupp->hasForms() )
107 // nothing to do at all
108 return false;
110 _rxForms.set(xFormsSupp->getForms(), UNO_QUERY);
111 Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important!
112 OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!");
113 if (!xSI.is())
114 return false;
116 if (!xSI->supportsService(u"com.sun.star.form.Forms"_ustr))
118 OSL_FAIL("OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!");
119 // nothing to do
120 return false;
122 return true;
125 void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn,
126 const Sequence< ScriptEventDescriptor >& _rEvents)
128 // do the exporting
129 OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents);
130 aExportImpl.doExport();
133 void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl,
134 const Sequence< ScriptEventDescriptor >& _rEvents)
136 // the list of the referring controls
137 OUString sReferringControls;
138 MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl);
139 if (aReferring != m_aCurrentPageReferring->second.end())
140 sReferringControls = aReferring->second;
142 // the control id (should already have been created in examineForms)
143 OUString sControlId( getControlId( _rxControl ) );
145 // do the exporting
146 OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents);
147 aExportImpl.doExport();
150 void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps,
151 const Sequence< ScriptEventDescriptor >& _rEvents)
153 OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!");
154 OFormExport aAttributeHandler(*this, _rxProps, _rEvents);
155 aAttributeHandler.doExport();
158 ::rtl::Reference< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper()
160 return m_xStyleExportMapper;
163 SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext()
165 return m_rContext;
168 void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection)
170 // step through all the elements of the collection
171 sal_Int32 nElements = _rxCollection->getCount();
173 Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY);
174 Sequence< ScriptEventDescriptor > aElementEvents;
176 Reference< XPropertySetInfo > xPropsInfo;
177 for (sal_Int32 i=0; i<nElements; ++i)
181 // extract the current element
182 Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY );
183 OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!");
184 if (!xCurrentProps.is())
185 continue;
187 // check if there is a ClassId property on the current element. If so, we assume it to be a control
188 xPropsInfo = xCurrentProps->getPropertySetInfo();
189 OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!");
190 if (!xPropsInfo.is())
191 // without this, a lot of stuff in the export routines may fail
192 continue;
194 // if the element is part of an ignore list, we are not allowed to export it
195 if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) )
196 continue;
198 if (xElementEventManager.is())
199 aElementEvents = xElementEventManager->getScriptEvents(i);
201 if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME))
203 exportGridColumn(xCurrentProps, aElementEvents);
205 else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID))
207 exportControl(xCurrentProps, aElementEvents);
209 else
211 exportForm(xCurrentProps, aElementEvents);
214 catch(Exception&)
216 TOOLS_WARN_EXCEPTION("xmloff.forms",
217 "caught an exception ... skipping the current element!");
218 continue;
223 OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject )
225 OUString aObjectStyle;
227 MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject );
228 if ( m_aGridColumnStyles.end() != aObjectStylePos )
229 aObjectStyle = aObjectStylePos->second;
230 return aObjectStyle;
233 void OFormLayerXMLExport_Impl::clear()
235 m_aControlIds.clear();
236 m_aReferringControls.clear();
237 m_aCurrentPageIds = m_aControlIds.end();
238 m_aCurrentPageReferring = m_aReferringControls.end();
240 m_aControlNumberFormats.clear();
241 m_aGridColumnStyles.clear();
243 m_aIgnoreList.clear();
246 void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles()
248 if ( m_pControlNumberStyles )
249 m_pControlNumberStyles->Export( true );
252 void OFormLayerXMLExport_Impl::exportAutoStyles()
254 m_rContext.GetAutoStylePool()->exportXML( XmlStyleFamily::CONTROL_ID );
257 void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage)
259 // get the forms collection of the page
260 Reference< XIndexAccess > xCollectionIndex;
261 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
263 return;
266 bool bPageIsKnown = implMoveIterators(_rxDrawPage, false);
267 OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!");
269 // export forms collection
270 exportCollectionElements(xCollectionIndex);
273 void OFormLayerXMLExport_Impl::exportXForms() const
275 // export XForms models
276 ::exportXForms( m_rContext );
279 bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage )
281 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
282 SAL_WARN_IF( !xFormsSupp.is(), "xmloff", "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" );
283 return xFormsSupp.is() && xFormsSupp->hasForms();
286 bool OFormLayerXMLExport_Impl::documentContainsXForms() const
288 Reference< css::xforms::XFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY );
289 Reference< XNameContainer > xForms;
290 if ( xXFormSupp.is() )
291 xForms = xXFormSupp->getXForms();
292 return xForms.is() && xForms->hasElements();
295 bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, bool _bClear)
297 if (!_rxDrawPage.is())
298 return false;
300 bool bKnownPage = false;
302 // the one for the ids
303 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
304 if (m_aControlIds.end() == m_aCurrentPageIds)
306 m_aControlIds[_rxDrawPage] = MapPropertySet2String();
307 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
309 else
311 bKnownPage = true;
312 if (_bClear && !m_aCurrentPageIds->second.empty() )
313 m_aCurrentPageIds->second.clear();
316 // the one for the ids of the referring controls
317 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
318 if (m_aReferringControls.end() == m_aCurrentPageReferring)
320 m_aReferringControls[_rxDrawPage] = MapPropertySet2String();
321 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
323 else
325 bKnownPage = true;
326 if (_bClear && !m_aCurrentPageReferring->second.empty() )
327 m_aCurrentPageReferring->second.clear();
329 return bKnownPage;
332 bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage)
334 bool bKnownPage = implMoveIterators( _rxDrawPage, false );
335 if ( bKnownPage )
336 return true;
338 // if the page is not yet known, this does not automatically mean that it has
339 // not been examined. Instead, examineForms returns silently and successfully
340 // if a page is a XFormsPageSupplier2, but does not have a forms collection
341 // (This behaviour of examineForms is a performance optimization, to not force
342 // the page to create a forms container just to see that it's empty.)
344 // So, in such a case, seekPage is considered to be successful, too, though the
345 // page was not yet known
346 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
347 if ( xFormsSupp.is() && !xFormsSupp->hasForms() )
348 return true;
350 // anything else means that the page has not been examined before, or it's no
351 // valid form page. Both cases are Bad (TM).
352 return false;
355 OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl)
357 if (m_aCurrentPageIds == m_aControlIds.end())
358 return OUString();
360 OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl),
361 "OFormLayerXMLExport_Impl::getControlId: can not find the control!");
362 return m_aCurrentPageIds->second[_rxControl];
365 OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject )
367 OUString sNumberStyle;
369 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject );
370 if ( -1 != nOwnFormatKey )
371 sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey );
373 return sNumberStyle;
376 OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl )
378 OUString sNumberStyle;
380 MapPropertySet2Int::const_iterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl);
381 if (m_aControlNumberFormats.end() != aControlFormatPos)
383 OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!");
384 sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second);
386 // it's allowed to ask for a control which does not have format information.
387 // (This is for performance reasons)
389 return sNumberStyle;
392 void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage)
394 // get the forms collection of the page
395 Reference< XIndexAccess > xCollectionIndex;
396 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
398 return;
401 // move the iterator which specify the currently handled page
402 bool bPageIsKnown = implMoveIterators(_rxDrawPage, true);
403 OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!");
405 ::std::stack< Reference< XIndexAccess > > aContainerHistory;
406 ::std::stack< sal_Int32 > aIndexHistory;
408 Reference< XIndexAccess > xLoop = xCollectionIndex;
409 sal_Int32 nChildPos = 0;
412 if (nChildPos < xLoop->getCount())
414 Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY );
415 OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object");
416 if (!xCurrent.is())
417 continue;
419 if (!checkExamineControl(xCurrent))
421 // step down
422 Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY);
423 OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?");
424 aContainerHistory.push(xLoop);
425 aIndexHistory.push(nChildPos);
427 xLoop = std::move(xNextContainer);
428 nChildPos = -1; // will be incremented below
430 ++nChildPos;
432 else
434 // step up
435 while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() )
437 xLoop = aContainerHistory.top();
438 aContainerHistory.pop();
439 nChildPos = aIndexHistory.top();
440 aIndexHistory.pop();
442 ++nChildPos;
444 if (nChildPos >= xLoop->getCount())
445 // exited the loop above because we have no history anymore (0 == aContainerHistory.size()),
446 // and on the current level there are no more children
447 // -> leave
448 break;
451 while (xLoop.is());
454 namespace
456 struct AccumulateSize
458 size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const
460 return _size + _map.second.size();
464 OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds )
466 OUString sControlId = u"control"_ustr;
468 size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), size_t(0), AccumulateSize() );
469 sControlId += OUString::number( static_cast<sal_Int32>(nKnownControlCount) + 1 );
471 #ifdef DBG_UTIL
472 // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries
473 // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if
474 // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail.
475 for ( const auto& outer : _rAllPagesControlIds )
476 for ( const auto& inner : outer.second )
478 OSL_ENSURE( inner.second != sControlId,
479 "lcl_findFreeControlId: auto-generated control ID is already used!" );
481 #endif
482 return sControlId;
486 bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject)
488 Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo();
489 OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info");
491 bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID );
492 if (bIsControl)
494 // generate a new control id
496 // find a free id
497 OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
498 // add it to the map
499 m_aCurrentPageIds->second[_rxObject] = sCurrentId;
501 // check if this control has a "LabelControl" property referring another control
502 if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) )
504 Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY );
505 if (xCurrentReference.is())
507 OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference];
508 if (!sReferencedBy.isEmpty())
509 // it's not the first _rxObject referring to the xCurrentReference
510 // -> separate the id
511 sReferencedBy += ",";
512 sReferencedBy += sCurrentId;
516 // check if the control needs a number format style
517 if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) )
519 examineControlNumberFormat(_rxObject);
522 // check if it's a control providing text
523 Reference< XText > xControlText( _rxObject, UNO_QUERY );
524 if ( xControlText.is() )
526 m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText );
529 // check if it is a grid control - in this case, we need special handling for the columns
530 sal_Int16 nControlType = FormComponentType::CONTROL;
531 _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType;
532 if ( FormComponentType::GRIDCONTROL == nControlType )
534 collectGridColumnStylesAndIds( _rxObject );
538 return bIsControl;
541 void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl )
543 // loop through all columns of the grid
546 Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY );
547 OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" );
548 if ( !xContainer.is() )
549 return;
551 Reference< XPropertySetInfo > xColumnPropertiesMeta;
553 sal_Int32 nCount = xContainer->getCount();
554 for ( sal_Int32 i=0; i<nCount; ++i )
556 Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY );
557 OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" );
558 if ( !xColumnProperties.is() )
559 continue;
561 // generate a new control id
563 // find a free id and add it to the map
564 m_aCurrentPageIds->second[xColumnProperties] = lcl_findFreeControlId(m_aControlIds);
566 // determine a number style, if needed
567 xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo();
568 // get the styles of the column
569 ::std::vector<XMLPropertyState> aPropertyStates = m_xStyleExportMapper->Filter(m_rContext, xColumnProperties);
571 // care for the number format, additionally
572 OUString sColumnNumberStyle;
573 if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) )
574 sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties );
576 if ( !sColumnNumberStyle.isEmpty() )
577 { // the column indeed has a formatting
578 sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE );
579 // TODO: move this to the ctor
580 OSL_ENSURE ( -1 != nStyleMapIndex, "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: could not obtain the index for our context id!");
582 XMLPropertyState aNumberStyleState( nStyleMapIndex, Any( sColumnNumberStyle ) );
583 aPropertyStates.push_back( aNumberStyleState );
586 // determine the column style
588 if ( !aPropertyStates.empty() )
589 { // add to the style pool
590 OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XmlStyleFamily::CONTROL_ID, std::move(aPropertyStates) );
592 OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ),
593 "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" );
595 m_aGridColumnStyles.emplace( xColumnProperties, sColumnStyleName );
599 catch( const Exception& )
601 DBG_UNHANDLED_EXCEPTION("xmloff.forms");
605 sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject )
607 // get the format key relative to our own formats supplier
608 sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject );
610 if ( -1 != nOwnFormatKey )
611 // tell the exporter that we used this format
612 getControlNumberStyleExport()->SetUsed( nOwnFormatKey );
614 return nOwnFormatKey;
617 void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl )
619 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl );
621 if ( -1 == nOwnFormatKey )
622 // nothing to do, the number format of this control is void
623 return;
625 // remember the format key for this control (we'll be asked in getControlNumberStyle for this)
626 OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl),
627 "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!");
628 m_aControlNumberFormats[_rxControl] = nOwnFormatKey;
631 sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl)
633 ensureControlNumberStyleExport();
634 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!");
635 // (should have been created in ensureControlNumberStyleExport)
637 sal_Int32 nOwnFormatKey = -1;
639 // the format key (relative to the control's supplier)
640 sal_Int32 nControlFormatKey = -1;
641 Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY);
642 if (aControlFormatKey >>= nControlFormatKey)
644 // the control's number format
645 Reference< XNumberFormatsSupplier > xControlFormatsSupplier;
646 _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier;
647 Reference< XNumberFormats > xControlFormats;
648 if (xControlFormatsSupplier.is())
649 xControlFormats = xControlFormatsSupplier->getNumberFormats();
650 OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!");
652 // obtain the persistent (does not depend on the formats supplier) representation of the control's format
653 Locale aFormatLocale;
654 OUString sFormatDescription;
655 if (xControlFormats.is())
657 Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey);
659 xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale;
660 xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription;
663 // check if our own formats collection already knows the format
664 nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, false);
665 if (-1 == nOwnFormatKey)
666 { // no, we don't
667 // -> create a new format
668 nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale);
670 OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!");
672 else
673 OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!");
675 return nOwnFormatKey;
678 void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport()
680 if (m_pControlNumberStyles)
681 return;
683 // create our number formats supplier (if necessary)
684 Reference< XNumberFormatsSupplier > xFormatsSupplier;
686 OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!");
687 // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together
691 // create it for en-US (does not really matter, as we will specify a locale for every
692 // concrete language to use)
693 Locale aLocale ( u"en"_ustr, u"US"_ustr, OUString() );
694 xFormatsSupplier = NumberFormatsSupplier::createWithLocale( m_rContext.getComponentContext(), aLocale );
695 m_xControlNumberFormats = xFormatsSupplier->getNumberFormats();
697 catch(const Exception&)
701 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!");
703 // create the exporter
704 m_pControlNumberStyles = std::make_unique<SvXMLNumFmtExport>(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix());
707 SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport()
709 ensureControlNumberStyleExport();
710 return m_pControlNumberStyles.get();
713 void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel >& _rxControl )
715 Reference< XPropertySet > xProps( _rxControl, UNO_QUERY );
716 OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" );
717 ::std::pair< PropertySetBag::const_iterator, bool > aPos =
718 m_aIgnoreList.insert( xProps );
719 OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" );
722 } // namespace xmloff
724 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */