| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmloff.hxx" |
| |
| #include <stdio.h> |
| #include "layerexport.hxx" |
| #include "strings.hxx" |
| #include <xmloff/xmlexp.hxx> |
| #include <xmloff/nmspmap.hxx> |
| #include "xmloff/xmlnmspe.hxx" |
| #include <xmloff/xmluconv.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 <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/xforms/XFormsSupplier.hpp> |
| #include <com/sun/star/form/FormComponentType.hpp> |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/container/XChild.hpp> |
| #include <com/sun/star/script/XEventAttacherManager.hpp> |
| #include "eventexport.hxx" |
| #include <xmloff/XMLEventExport.hxx> |
| #include "formevents.hxx" |
| #include <xmloff/xmlnumfe.hxx> |
| #include "xmloff/xformsexport.hxx" |
| |
| /** === begin UNO includes === **/ |
| #include <com/sun/star/text/XText.hpp> |
| /** === end UNO includes === **/ |
| |
| #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; |
| |
| typedef ::com::sun::star::xforms::XFormsSupplier XXFormsSupplier; |
| |
| //===================================================================== |
| //= OFormLayerXMLExport_Impl |
| //===================================================================== |
| //--------------------------------------------------------------------- |
| const ::rtl::OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix() |
| { |
| static const ::rtl::OUString s_sControlNumberStyleNamePrefix = ::rtl::OUString::createFromAscii("C"); |
| return s_sControlNumberStyleNamePrefix; |
| } |
| |
| //--------------------------------------------------------------------- |
| OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext) |
| :m_rContext(_rContext) |
| ,m_pControlNumberStyles(NULL) |
| { |
| initializePropertyMaps(); |
| |
| // add our style family to the export context's style pool |
| m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory(); |
| ::vos::ORef< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory.getBodyPtr() ); |
| m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper.getBodyPtr() ); |
| |
| // our style family |
| m_rContext.GetAutoStylePool()->AddFamily( |
| XML_STYLE_FAMILY_CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH), |
| m_xStyleExportMapper.getBodyPtr(), |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XML_STYLE_FAMILY_CONTROL_PREFIX) ) |
| ); |
| |
| // add our event translation table |
| m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation); |
| |
| clear(); |
| } |
| |
| OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl() |
| { |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_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 sal_False; |
| |
| if ( !xFormsSupp->hasForms() ) |
| // nothing to do at all |
| return sal_False; |
| |
| _rxForms = Reference< XIndexAccess >(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 sal_False; |
| |
| if (!xSI->supportsService(SERVICE_FORMSCOLLECTION)) |
| { |
| OSL_ENSURE(sal_False, "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!"); |
| // nothing to do |
| return sal_False; |
| } |
| return sal_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 |
| ::rtl::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) |
| ::rtl::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(); |
| } |
| |
| //--------------------------------------------------------------------- |
| ::vos::ORef< 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; |
| Reference< XIndexAccess > xCurrentContainer; |
| 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 a 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&) |
| { |
| OSL_ENSURE(sal_False, "OFormLayerXMLExport_Impl::exportCollectionElements: caught an exception ... skipping the current element!"); |
| continue; |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------- |
| ::rtl::OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject ) |
| { |
| ::rtl::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::exportControlNumberStyles() |
| { |
| if (m_pControlNumberStyles) |
| m_pControlNumberStyles->Export(sal_False); |
| } |
| |
| //--------------------------------------------------------------------- |
| void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles() |
| { |
| if ( m_pControlNumberStyles ) |
| m_pControlNumberStyles->Export( sal_True ); |
| } |
| |
| //--------------------------------------------------------------------- |
| void OFormLayerXMLExport_Impl::exportAutoStyles() |
| { |
| m_rContext.GetAutoStylePool()->exportXML( |
| XML_STYLE_FAMILY_CONTROL_ID, |
| m_rContext.GetDocHandler(), |
| m_rContext.GetMM100UnitConverter(), |
| m_rContext.GetNamespaceMap() |
| ); |
| } |
| |
| //--------------------------------------------------------------------- |
| void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage) |
| { |
| // get the forms collection of the page |
| Reference< XIndexAccess > xCollectionIndex; |
| if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex)) |
| return; |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| sal_Bool bPageIsKnown = |
| #endif |
| implMoveIterators(_rxDrawPage, sal_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 ) const |
| { |
| Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY ); |
| DBG_ASSERT( xFormsSupp.is(), "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" ); |
| return xFormsSupp.is() && xFormsSupp->hasForms(); |
| } |
| |
| //--------------------------------------------------------------------- |
| bool OFormLayerXMLExport_Impl::documentContainsXForms() const |
| { |
| Reference< XXFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY ); |
| Reference< XNameContainer > xForms; |
| if ( xXFormSupp.is() ) |
| xForms = xXFormSupp->getXForms(); |
| return xForms.is() && xForms->hasElements(); |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, sal_Bool _bClear) |
| { |
| sal_Bool bKnownPage = sal_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 = sal_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 = sal_True; |
| if (_bClear && !m_aCurrentPageReferring->second.empty() ) |
| m_aCurrentPageReferring->second.clear(); |
| } |
| return bKnownPage; |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage) |
| { |
| sal_Bool bKnownPage = implMoveIterators( _rxDrawPage, sal_False ); |
| if ( bKnownPage ) |
| return sal_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 successfull, too, though the |
| // page was not yet known |
| Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY ); |
| if ( xFormsSupp.is() && !xFormsSupp->hasForms() ) |
| return sal_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 sal_False; |
| } |
| |
| //--------------------------------------------------------------------- |
| ::rtl::OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl) |
| { |
| OSL_ENSURE(m_aCurrentPageIds != m_aControlIds.end(), "OFormLayerXMLExport_Impl::getControlId: invalid current page!"); |
| OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl), |
| "OFormLayerXMLExport_Impl::getControlId: can not find the control!"); |
| return m_aCurrentPageIds->second[_rxControl]; |
| } |
| |
| //--------------------------------------------------------------------- |
| ::rtl::OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject ) |
| { |
| ::rtl::OUString sNumberStyle; |
| |
| sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject ); |
| if ( -1 != nOwnFormatKey ) |
| sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey ); |
| |
| return sNumberStyle; |
| } |
| |
| //--------------------------------------------------------------------- |
| ::rtl::OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl ) |
| { |
| ::rtl::OUString sNumberStyle; |
| |
| ConstMapPropertySet2IntIterator 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 |
| #if OSL_DEBUG_LEVEL > 0 |
| sal_Bool bPageIsKnown = |
| #endif |
| implMoveIterators(_rxDrawPage, sal_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 : public ::std::binary_function< size_t, MapPropertySet2Map::value_type, size_t > |
| { |
| size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const |
| { |
| return _size + _map.second.size(); |
| } |
| }; |
| |
| ::rtl::OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds ) |
| { |
| static const ::rtl::OUString sControlIdBase( RTL_CONSTASCII_USTRINGPARAM( "control" ) ); |
| ::rtl::OUString sControlId = sControlIdBase; |
| |
| size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), (size_t)0, AccumulateSize() ); |
| sControlId += ::rtl::OUString::valueOf( (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 ( MapPropertySet2Map::const_iterator outer = _rAllPagesControlIds.begin(); |
| outer != _rAllPagesControlIds.end(); |
| ++outer |
| ) |
| for ( MapPropertySet2String::const_iterator inner = outer->second.begin(); |
| inner != outer->second.end(); |
| ++inner |
| ) |
| { |
| OSL_ENSURE( inner->second != sControlId, |
| "lcl_findFreeControlId: auto-generated control ID is already used!" ); |
| } |
| #endif |
| return sControlId; |
| } |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject) |
| { |
| Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo(); |
| OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info"); |
| |
| sal_Bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID ); |
| if (bIsControl) |
| { |
| // ---------------------------------- |
| // generate a new control id |
| |
| // find a free id |
| ::rtl::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()) |
| { |
| ::rtl::OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference]; |
| if (sReferencedBy.getLength()) |
| // it's not the first _rxObject referring to the xCurrentReference |
| // -> separate the id |
| sReferencedBy += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); |
| 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 |
| ::rtl::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( xColumnProperties ); |
| |
| // care for the number format, additionally |
| ::rtl::OUString sColumnNumberStyle; |
| if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) ) |
| sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties ); |
| |
| if ( sColumnNumberStyle.getLength() ) |
| { // 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, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!"); |
| |
| XMLPropertyState aNumberStyleState( nStyleMapIndex, makeAny( sColumnNumberStyle ) ); |
| aPropertyStates.push_back( aNumberStyleState ); |
| } |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| ::std::vector< XMLPropertyState >::const_iterator aHaveALook = aPropertyStates.begin(); |
| for ( ; aHaveALook != aPropertyStates.end(); ++aHaveALook ) |
| { |
| (void)aHaveALook; |
| } |
| #endif |
| |
| // ---------------------------------- |
| // determine the column style |
| |
| if ( !aPropertyStates.empty() ) |
| { // add to the style pool |
| ::rtl::OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XML_STYLE_FAMILY_CONTROL_ID, aPropertyStates ); |
| |
| OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ), |
| "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" ); |
| |
| m_aGridColumnStyles.insert( MapPropertySet2String::value_type( xColumnProperties, sColumnStyleName ) ); |
| } |
| } |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| |
| //--------------------------------------------------------------------- |
| 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; |
| ::rtl::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, sal_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) |
| { |
| // 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) |
| Sequence< Any > aSupplierArgs(1); |
| aSupplierArgs[0] <<= Locale ( ::rtl::OUString::createFromAscii("en"), |
| ::rtl::OUString::createFromAscii("US"), |
| ::rtl::OUString() |
| ); |
| // #110680# |
| //Reference< XInterface > xFormatsSupplierUntyped = |
| // ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( |
| // SERVICE_NUMBERFORMATSSUPPLIER, |
| // aSupplierArgs |
| // ); |
| Reference< XInterface > xFormatsSupplierUntyped = |
| m_rContext.getServiceFactory()->createInstanceWithArguments( |
| SERVICE_NUMBERFORMATSSUPPLIER, |
| aSupplierArgs |
| ); |
| OSL_ENSURE(xFormatsSupplierUntyped.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not instantiate a number formats supplier!"); |
| |
| xFormatsSupplier = Reference< XNumberFormatsSupplier >(xFormatsSupplierUntyped, UNO_QUERY); |
| if (xFormatsSupplier.is()) |
| 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!" ); |
| #if OSL_DEBUG_LEVEL > 0 |
| ::std::pair< PropertySetBag::iterator, bool > aPos = |
| #endif |
| m_aIgnoreList.insert( xProps ); |
| OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" ); |
| } |
| |
| //......................................................................... |
| } // namespace xmloff |
| //......................................................................... |
| |
| |