1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
);
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
);
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())
106 if ( !xFormsSupp
->hasForms() )
107 // nothing to do at all
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)!");
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)!");
125 void OFormLayerXMLExport_Impl::exportGridColumn(const Reference
< XPropertySet
>& _rxColumn
,
126 const Sequence
< ScriptEventDescriptor
>& _rEvents
)
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
) );
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()
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())
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
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
) )
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
);
211 exportForm(xCurrentProps
, aElementEvents
);
216 TOOLS_WARN_EXCEPTION("xmloff.forms",
217 "caught an exception ... skipping the current element!");
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
;
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
))
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())
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
);
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
);
326 if (_bClear
&& !m_aCurrentPageReferring
->second
.empty() )
327 m_aCurrentPageReferring
->second
.clear();
332 bool OFormLayerXMLExport_Impl::seekPage(const Reference
< XDrawPage
>& _rxDrawPage
)
334 bool bKnownPage
= implMoveIterators( _rxDrawPage
, false );
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() )
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).
355 OUString
OFormLayerXMLExport_Impl::getControlId(const Reference
< XPropertySet
>& _rxControl
)
357 if (m_aCurrentPageIds
== m_aControlIds
.end())
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
);
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)
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
))
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");
419 if (!checkExamineControl(xCurrent
))
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
435 while ((nChildPos
>= xLoop
->getCount()) && !aContainerHistory
.empty() )
437 xLoop
= aContainerHistory
.top();
438 aContainerHistory
.pop();
439 nChildPos
= aIndexHistory
.top();
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
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 );
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!" );
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
);
494 // generate a new control id
497 OUString sCurrentId
= lcl_findFreeControlId( m_aControlIds
);
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
);
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() )
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() )
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
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
)
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!");
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
)
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: */