summaryrefslogtreecommitdiffstats
path: root/xmloff/source/forms/layerexport.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmloff/source/forms/layerexport.cxx')
-rw-r--r--xmloff/source/forms/layerexport.cxx727
1 files changed, 727 insertions, 0 deletions
diff --git a/xmloff/source/forms/layerexport.cxx b/xmloff/source/forms/layerexport.cxx
new file mode 100644
index 000000000..87c3b5b40
--- /dev/null
+++ b/xmloff/source/forms/layerexport.cxx
@@ -0,0 +1,727 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "layerexport.hxx"
+#include "strings.hxx"
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/prhdlfac.hxx>
+#include "elementexport.hxx"
+#include <xmloff/families.hxx>
+#include <xmloff/contextid.hxx>
+#include <xmloff/controlpropertyhdl.hxx>
+#include <xmloff/maptype.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include "controlpropertymap.hxx"
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/form/XFormsSupplier2.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xforms/XFormsSupplier.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/util/NumberFormatsSupplier.hpp>
+#include <xmloff/XMLEventExport.hxx>
+#include "formevents.hxx"
+#include <xmloff/xmlnumfe.hxx>
+#include <xmloff/xformsexport.hxx>
+
+#include <com/sun/star/text/XText.hpp>
+
+#include <stack>
+#include <numeric>
+
+namespace xmloff
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::drawing;
+ using namespace ::com::sun::star::form;
+ using namespace ::com::sun::star::script;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::text;
+
+ //= OFormLayerXMLExport_Impl
+ const OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix()
+ {
+ static const OUString s_sControlNumberStyleNamePrefix("C");
+ return s_sControlNumberStyleNamePrefix;
+ }
+
+ OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext)
+ :m_rContext(_rContext)
+ ,m_pControlNumberStyles(nullptr)
+ {
+ initializePropertyMaps();
+
+ // add our style family to the export context's style pool
+ m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory();
+ ::rtl::Reference< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory, true );
+ m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper );
+
+ // our style family
+ m_rContext.GetAutoStylePool()->AddFamily(
+ XmlStyleFamily::CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH),
+ m_xStyleExportMapper.get(),
+ OUString( XML_STYLE_FAMILY_CONTROL_PREFIX )
+ );
+
+ // add our event translation table
+ m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation);
+
+ clear();
+ }
+
+ OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl()
+ {
+ }
+
+ bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms)
+ {
+ Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY);
+ OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!");
+ if (!xFormsSupp.is())
+ return false;
+
+ if ( !xFormsSupp->hasForms() )
+ // nothing to do at all
+ return false;
+
+ _rxForms.set(xFormsSupp->getForms(), UNO_QUERY);
+ Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important!
+ OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!");
+ if (!xSI.is())
+ return false;
+
+ if (!xSI->supportsService("com.sun.star.form.Forms"))
+ {
+ OSL_FAIL("OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!");
+ // nothing to do
+ return false;
+ }
+ return true;
+ }
+
+ void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn,
+ const Sequence< ScriptEventDescriptor >& _rEvents)
+ {
+ // do the exporting
+ OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents);
+ aExportImpl.doExport();
+ }
+
+ void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl,
+ const Sequence< ScriptEventDescriptor >& _rEvents)
+ {
+ // the list of the referring controls
+ OUString sReferringControls;
+ MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl);
+ if (aReferring != m_aCurrentPageReferring->second.end())
+ sReferringControls = aReferring->second;
+
+ // the control id (should already have been created in examineForms)
+ OUString sControlId( getControlId( _rxControl ) );
+
+ // do the exporting
+ OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents);
+ aExportImpl.doExport();
+ }
+
+ void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps,
+ const Sequence< ScriptEventDescriptor >& _rEvents)
+ {
+ OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!");
+ OFormExport aAttributeHandler(*this, _rxProps, _rEvents);
+ aAttributeHandler.doExport();
+ }
+
+ ::rtl::Reference< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper()
+ {
+ return m_xStyleExportMapper;
+ }
+
+ SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext()
+ {
+ return m_rContext;
+ }
+
+ void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection)
+ {
+ // step through all the elements of the collection
+ sal_Int32 nElements = _rxCollection->getCount();
+
+ Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY);
+ Sequence< ScriptEventDescriptor > aElementEvents;
+
+ Reference< XPropertySetInfo > xPropsInfo;
+ for (sal_Int32 i=0; i<nElements; ++i)
+ {
+ try
+ {
+ // extract the current element
+ Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY );
+ OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!");
+ if (!xCurrentProps.is())
+ continue;
+
+ // check if there is a ClassId property on the current element. If so, we assume it to be a control
+ xPropsInfo = xCurrentProps->getPropertySetInfo();
+ OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!");
+ if (!xPropsInfo.is())
+ // without this, a lot of stuff in the export routines may fail
+ continue;
+
+ // if the element is part of an ignore list, we are not allowed to export it
+ if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) )
+ continue;
+
+ if (xElementEventManager.is())
+ aElementEvents = xElementEventManager->getScriptEvents(i);
+
+ if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME))
+ {
+ exportGridColumn(xCurrentProps, aElementEvents);
+ }
+ else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID))
+ {
+ exportControl(xCurrentProps, aElementEvents);
+ }
+ else
+ {
+ exportForm(xCurrentProps, aElementEvents);
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.forms",
+ "caught an exception ... skipping the current element!");
+ continue;
+ }
+ }
+ }
+
+ OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject )
+ {
+ OUString aObjectStyle;
+
+ MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject );
+ if ( m_aGridColumnStyles.end() != aObjectStylePos )
+ aObjectStyle = aObjectStylePos->second;
+ return aObjectStyle;
+ }
+
+ void OFormLayerXMLExport_Impl::clear()
+ {
+ m_aControlIds.clear();
+ m_aReferringControls.clear();
+ m_aCurrentPageIds = m_aControlIds.end();
+ m_aCurrentPageReferring = m_aReferringControls.end();
+
+ m_aControlNumberFormats.clear();
+ m_aGridColumnStyles.clear();
+
+ m_aIgnoreList.clear();
+ }
+
+ void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles()
+ {
+ if ( m_pControlNumberStyles )
+ m_pControlNumberStyles->Export( true );
+ }
+
+ void OFormLayerXMLExport_Impl::exportAutoStyles()
+ {
+ m_rContext.GetAutoStylePool()->exportXML( XmlStyleFamily::CONTROL_ID );
+ }
+
+ void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage)
+ {
+ // get the forms collection of the page
+ Reference< XIndexAccess > xCollectionIndex;
+ if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
+ {
+ return;
+ }
+
+ bool bPageIsKnown = implMoveIterators(_rxDrawPage, false);
+ OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!");
+
+ // export forms collection
+ exportCollectionElements(xCollectionIndex);
+ }
+
+ void OFormLayerXMLExport_Impl::exportXForms() const
+ {
+ // export XForms models
+ ::exportXForms( m_rContext );
+ }
+
+ bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage )
+ {
+ Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
+ SAL_WARN_IF( !xFormsSupp.is(), "xmloff", "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" );
+ return xFormsSupp.is() && xFormsSupp->hasForms();
+ }
+
+ bool OFormLayerXMLExport_Impl::documentContainsXForms() const
+ {
+ Reference< css::xforms::XFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY );
+ Reference< XNameContainer > xForms;
+ if ( xXFormSupp.is() )
+ xForms = xXFormSupp->getXForms();
+ return xForms.is() && xForms->hasElements();
+ }
+
+ bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, bool _bClear)
+ {
+ if (!_rxDrawPage.is())
+ return false;
+
+ bool bKnownPage = false;
+
+ // the one for the ids
+ m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
+ if (m_aControlIds.end() == m_aCurrentPageIds)
+ {
+ m_aControlIds[_rxDrawPage] = MapPropertySet2String();
+ m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
+ }
+ else
+ {
+ bKnownPage = true;
+ if (_bClear && !m_aCurrentPageIds->second.empty() )
+ m_aCurrentPageIds->second.clear();
+ }
+
+ // the one for the ids of the referring controls
+ m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
+ if (m_aReferringControls.end() == m_aCurrentPageReferring)
+ {
+ m_aReferringControls[_rxDrawPage] = MapPropertySet2String();
+ m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
+ }
+ else
+ {
+ bKnownPage = true;
+ if (_bClear && !m_aCurrentPageReferring->second.empty() )
+ m_aCurrentPageReferring->second.clear();
+ }
+ return bKnownPage;
+ }
+
+ bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage)
+ {
+ bool bKnownPage = implMoveIterators( _rxDrawPage, false );
+ if ( bKnownPage )
+ return true;
+
+ // if the page is not yet known, this does not automatically mean that it has
+ // not been examined. Instead, examineForms returns silently and successfully
+ // if a page is a XFormsPageSupplier2, but does not have a forms collection
+ // (This behaviour of examineForms is a performance optimization, to not force
+ // the page to create a forms container just to see that it's empty.)
+
+ // So, in such a case, seekPage is considered to be successful, too, though the
+ // page was not yet known
+ Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
+ if ( xFormsSupp.is() && !xFormsSupp->hasForms() )
+ return true;
+
+ // anything else means that the page has not been examined before, or it's no
+ // valid form page. Both cases are Bad (TM).
+ return false;
+ }
+
+ OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl)
+ {
+ if (m_aCurrentPageIds == m_aControlIds.end())
+ return OUString();
+
+ OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl),
+ "OFormLayerXMLExport_Impl::getControlId: can not find the control!");
+ return m_aCurrentPageIds->second[_rxControl];
+ }
+
+ OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject )
+ {
+ OUString sNumberStyle;
+
+ sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject );
+ if ( -1 != nOwnFormatKey )
+ sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey );
+
+ return sNumberStyle;
+ }
+
+ OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl )
+ {
+ OUString sNumberStyle;
+
+ MapPropertySet2Int::const_iterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl);
+ if (m_aControlNumberFormats.end() != aControlFormatPos)
+ {
+ OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!");
+ sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second);
+ }
+ // it's allowed to ask for a control which does not have format information.
+ // (This is for performance reasons)
+
+ return sNumberStyle;
+ }
+
+ void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage)
+ {
+ // get the forms collection of the page
+ Reference< XIndexAccess > xCollectionIndex;
+ if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
+ {
+ return;
+ }
+
+ // move the iterator which specify the currently handled page
+ bool bPageIsKnown = implMoveIterators(_rxDrawPage, true);
+ OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!");
+
+ ::std::stack< Reference< XIndexAccess > > aContainerHistory;
+ ::std::stack< sal_Int32 > aIndexHistory;
+
+ Reference< XIndexAccess > xLoop = xCollectionIndex;
+ sal_Int32 nChildPos = 0;
+ do
+ {
+ if (nChildPos < xLoop->getCount())
+ {
+ Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY );
+ OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object");
+ if (!xCurrent.is())
+ continue;
+
+ if (!checkExamineControl(xCurrent))
+ {
+ // step down
+ Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY);
+ OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?");
+ aContainerHistory.push(xLoop);
+ aIndexHistory.push(nChildPos);
+
+ xLoop = xNextContainer;
+ nChildPos = -1; // will be incremented below
+ }
+ ++nChildPos;
+ }
+ else
+ {
+ // step up
+ while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() )
+ {
+ xLoop = aContainerHistory.top();
+ aContainerHistory.pop();
+ nChildPos = aIndexHistory.top();
+ aIndexHistory.pop();
+
+ ++nChildPos;
+ }
+ if (nChildPos >= xLoop->getCount())
+ // exited the loop above because we have no history anymore (0 == aContainerHistory.size()),
+ // and on the current level there are no more children
+ // -> leave
+ break;
+ }
+ }
+ while (xLoop.is());
+ }
+
+ namespace
+ {
+ struct AccumulateSize
+ {
+ size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const
+ {
+ return _size + _map.second.size();
+ }
+ };
+
+ OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds )
+ {
+ OUString sControlId = "control";
+
+ size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), size_t(0), AccumulateSize() );
+ sControlId += OUString::number( static_cast<sal_Int32>(nKnownControlCount) + 1 );
+
+ #ifdef DBG_UTIL
+ // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries
+ // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if
+ // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail.
+ for ( const auto& outer : _rAllPagesControlIds )
+ for ( const auto& inner : outer.second )
+ {
+ OSL_ENSURE( inner.second != sControlId,
+ "lcl_findFreeControlId: auto-generated control ID is already used!" );
+ }
+ #endif
+ return sControlId;
+ }
+ }
+
+ bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject)
+ {
+ Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo();
+ OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info");
+
+ bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID );
+ if (bIsControl)
+ {
+ // generate a new control id
+
+ // find a free id
+ OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
+ // add it to the map
+ m_aCurrentPageIds->second[_rxObject] = sCurrentId;
+
+ // check if this control has a "LabelControl" property referring another control
+ if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) )
+ {
+ Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY );
+ if (xCurrentReference.is())
+ {
+ OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference];
+ if (!sReferencedBy.isEmpty())
+ // it's not the first _rxObject referring to the xCurrentReference
+ // -> separate the id
+ sReferencedBy += ",";
+ sReferencedBy += sCurrentId;
+ }
+ }
+
+ // check if the control needs a number format style
+ if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) )
+ {
+ examineControlNumberFormat(_rxObject);
+ }
+
+ // check if it's a control providing text
+ Reference< XText > xControlText( _rxObject, UNO_QUERY );
+ if ( xControlText.is() )
+ {
+ m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText );
+ }
+
+ // check if it is a grid control - in this case, we need special handling for the columns
+ sal_Int16 nControlType = FormComponentType::CONTROL;
+ _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType;
+ if ( FormComponentType::GRIDCONTROL == nControlType )
+ {
+ collectGridColumnStylesAndIds( _rxObject );
+ }
+ }
+
+ return bIsControl;
+ }
+
+ void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl )
+ {
+ // loop through all columns of the grid
+ try
+ {
+ Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY );
+ OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" );
+ if ( !xContainer.is() )
+ return;
+
+ Reference< XPropertySetInfo > xColumnPropertiesMeta;
+
+ sal_Int32 nCount = xContainer->getCount();
+ for ( sal_Int32 i=0; i<nCount; ++i )
+ {
+ Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY );
+ OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" );
+ if ( !xColumnProperties.is() )
+ continue;
+
+ // generate a new control id
+
+ // find a free id
+ OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
+ // add it to the map
+ m_aCurrentPageIds->second[ xColumnProperties ] = sCurrentId;
+
+ // determine a number style, if needed
+ xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo();
+ // get the styles of the column
+ ::std::vector<XMLPropertyState> aPropertyStates = m_xStyleExportMapper->Filter(m_rContext, xColumnProperties);
+
+ // care for the number format, additionally
+ OUString sColumnNumberStyle;
+ if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) )
+ sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties );
+
+ if ( !sColumnNumberStyle.isEmpty() )
+ { // the column indeed has a formatting
+ sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE );
+ // TODO: move this to the ctor
+ OSL_ENSURE ( -1 != nStyleMapIndex, "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: could not obtain the index for our context id!");
+
+ XMLPropertyState aNumberStyleState( nStyleMapIndex, Any( sColumnNumberStyle ) );
+ aPropertyStates.push_back( aNumberStyleState );
+ }
+
+ // determine the column style
+
+ if ( !aPropertyStates.empty() )
+ { // add to the style pool
+ OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XmlStyleFamily::CONTROL_ID, std::move(aPropertyStates) );
+
+ OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ),
+ "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" );
+
+ m_aGridColumnStyles.emplace( xColumnProperties, sColumnStyleName );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("xmloff.forms");
+ }
+ }
+
+ sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject )
+ {
+ // get the format key relative to our own formats supplier
+ sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject );
+
+ if ( -1 != nOwnFormatKey )
+ // tell the exporter that we used this format
+ getControlNumberStyleExport()->SetUsed( nOwnFormatKey );
+
+ return nOwnFormatKey;
+ }
+
+ void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl )
+ {
+ sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl );
+
+ if ( -1 == nOwnFormatKey )
+ // nothing to do, the number format of this control is void
+ return;
+
+ // remember the format key for this control (we'll be asked in getControlNumberStyle for this)
+ OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl),
+ "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!");
+ m_aControlNumberFormats[_rxControl] = nOwnFormatKey;
+ }
+
+ sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl)
+ {
+ ensureControlNumberStyleExport();
+ OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!");
+ // (should have been created in ensureControlNumberStyleExport)
+
+ sal_Int32 nOwnFormatKey = -1;
+
+ // the format key (relative to the control's supplier)
+ sal_Int32 nControlFormatKey = -1;
+ Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY);
+ if (aControlFormatKey >>= nControlFormatKey)
+ {
+ // the control's number format
+ Reference< XNumberFormatsSupplier > xControlFormatsSupplier;
+ _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier;
+ Reference< XNumberFormats > xControlFormats;
+ if (xControlFormatsSupplier.is())
+ xControlFormats = xControlFormatsSupplier->getNumberFormats();
+ OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!");
+
+ // obtain the persistent (does not depend on the formats supplier) representation of the control's format
+ Locale aFormatLocale;
+ OUString sFormatDescription;
+ if (xControlFormats.is())
+ {
+ Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey);
+
+ xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale;
+ xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription;
+ }
+
+ // check if our own formats collection already knows the format
+ nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, false);
+ if (-1 == nOwnFormatKey)
+ { // no, we don't
+ // -> create a new format
+ nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale);
+ }
+ OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!");
+ }
+ else
+ OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!");
+
+ return nOwnFormatKey;
+ }
+
+ void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport()
+ {
+ if (m_pControlNumberStyles)
+ return;
+
+ // create our number formats supplier (if necessary)
+ Reference< XNumberFormatsSupplier > xFormatsSupplier;
+
+ OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!");
+ // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together
+
+ try
+ {
+ // create it for en-US (does not really matter, as we will specify a locale for every
+ // concrete language to use)
+ Locale aLocale ( "en", "US", OUString() );
+ xFormatsSupplier = NumberFormatsSupplier::createWithLocale( m_rContext.getComponentContext(), aLocale );
+ m_xControlNumberFormats = xFormatsSupplier->getNumberFormats();
+ }
+ catch(const Exception&)
+ {
+ }
+
+ OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!");
+
+ // create the exporter
+ m_pControlNumberStyles = new SvXMLNumFmtExport(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix());
+ }
+
+ SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport()
+ {
+ ensureControlNumberStyleExport();
+ return m_pControlNumberStyles;
+ }
+
+ void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel >& _rxControl )
+ {
+ Reference< XPropertySet > xProps( _rxControl, UNO_QUERY );
+ OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" );
+ ::std::pair< PropertySetBag::const_iterator, bool > aPos =
+ m_aIgnoreList.insert( xProps );
+ OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" );
+ }
+
+} // namespace xmloff
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */