diff options
Diffstat (limited to 'xmloff/source/forms')
50 files changed, 15226 insertions, 0 deletions
diff --git a/xmloff/source/forms/attriblistmerge.cxx b/xmloff/source/forms/attriblistmerge.cxx new file mode 100644 index 000000000000..0a057377e91f --- /dev/null +++ b/xmloff/source/forms/attriblistmerge.cxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "attriblistmerge.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::xml; + + //===================================================================== + //= OAttribListMerger + //===================================================================== + //--------------------------------------------------------------------- + void OAttribListMerger::addList(const Reference< sax::XAttributeList >& _rxList) + { + OSL_ENSURE(_rxList.is(), "OAttribListMerger::addList: invalid list!"); + if (_rxList.is()) + m_aLists.push_back(_rxList); + } + + //--------------------------------------------------------------------- + sal_Bool OAttribListMerger::seekToIndex(sal_Int16 _nGlobalIndex, Reference< sax::XAttributeList >& _rSubList, sal_Int16& _rLocalIndex) + { + sal_Int16 nLeftOver = _nGlobalIndex; + ConstAttributeListArrayIterator aLookupSublist = m_aLists.begin(); + + for ( ; (aLookupSublist != m_aLists.end()) && (nLeftOver >= (*aLookupSublist)->getLength()); + ++aLookupSublist + ) + nLeftOver = nLeftOver - (*aLookupSublist)->getLength(); + + if (aLookupSublist == m_aLists.end()) + { + OSL_ENSURE(sal_False, "OAttribListMerger::seekToIndex: invalid index!"); + return sal_False; + } + _rSubList = *aLookupSublist; + _rLocalIndex = nLeftOver; + return sal_True; + } + + //--------------------------------------------------------------------- + sal_Bool OAttribListMerger::seekToName(const ::rtl::OUString& _rName, Reference< sax::XAttributeList >& _rSubList, sal_Int16& _rLocalIndex) + { + for ( ConstAttributeListArrayIterator aLookupSublist = m_aLists.begin(); + aLookupSublist != m_aLists.end(); + ++aLookupSublist + ) + for (sal_Int16 i=0; i<(*aLookupSublist)->getLength(); ++i) + if ((*aLookupSublist)->getNameByIndex(i) == _rName) + { + _rSubList = *aLookupSublist; + _rLocalIndex = i; + return sal_True; + } + + OSL_ENSURE(sal_False, "OAttribListMerger::seekToName: did not find the name!"); + return sal_False; + } + + //--------------------------------------------------------------------- + sal_Int16 SAL_CALL OAttribListMerger::getLength( ) throw(RuntimeException) + { + sal_Int16 nCount = 0; + for ( ConstAttributeListArrayIterator aAccumulate = m_aLists.begin(); + aAccumulate != m_aLists.end(); + ++aAccumulate + ) + nCount = nCount + (*aAccumulate)->getLength(); + return nCount; + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAttribListMerger::getNameByIndex( sal_Int16 i ) throw(RuntimeException) + { + Reference< sax::XAttributeList > xSubList; + sal_Int16 nLocalIndex; + + if (!seekToIndex(i, xSubList, nLocalIndex)) + return ::rtl::OUString(); + + return xSubList->getNameByIndex(nLocalIndex); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAttribListMerger::getTypeByIndex( sal_Int16 i ) throw(RuntimeException) + { + Reference< sax::XAttributeList > xSubList; + sal_Int16 nLocalIndex; + + if (!seekToIndex(i, xSubList, nLocalIndex)) + return ::rtl::OUString(); + + return xSubList->getTypeByIndex(nLocalIndex); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAttribListMerger::getTypeByName( const ::rtl::OUString& _rName ) throw(RuntimeException) + { + Reference< sax::XAttributeList > xSubList; + sal_Int16 nLocalIndex; + + if (!seekToName(_rName, xSubList, nLocalIndex)) + return ::rtl::OUString(); + + // though we're in getTypeByName here, we reroute this to the getTypeByIndex of the sub list, + // assuming that this is faster + return xSubList->getTypeByIndex(nLocalIndex); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAttribListMerger::getValueByIndex( sal_Int16 i ) throw(RuntimeException) + { + Reference< sax::XAttributeList > xSubList; + sal_Int16 nLocalIndex; + + if (!seekToIndex(i, xSubList, nLocalIndex)) + return ::rtl::OUString(); + + return xSubList->getValueByIndex(nLocalIndex); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAttribListMerger::getValueByName( const ::rtl::OUString& _rName ) throw(RuntimeException) + { + Reference< sax::XAttributeList > xSubList; + sal_Int16 nLocalIndex; + + if (!seekToName(_rName, xSubList, nLocalIndex)) + return ::rtl::OUString(); + + // though we're in getValueByName here, we reroute this to the getValueByIndex of the sub list, + // assuming that this is faster + return xSubList->getValueByIndex(nLocalIndex); + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/attriblistmerge.hxx b/xmloff/source/forms/attriblistmerge.hxx new file mode 100644 index 000000000000..7d88060a5eed --- /dev/null +++ b/xmloff/source/forms/attriblistmerge.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_ATTRIBLISTMERGE_HXX_ +#define _XMLOFF_FORMS_ATTRIBLISTMERGE_HXX_ + +#include <comphelper/stl_types.hxx> +#include <cppuhelper/implbase1.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/xml/sax/XAttributeList.hpp> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OAttribListMerger + //===================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::xml::sax::XAttributeList + > OAttribListMerger_Base; + /** implements the XAttributeList list by merging different source attribute lists + + <p>Currently, the time behavious is O(n), though it would be possible to change it to O(log n).</p> + */ + class OAttribListMerger : public OAttribListMerger_Base + { + protected: + ::osl::Mutex m_aMutex; + DECLARE_STL_VECTOR( ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >, AttributeListArray ); + AttributeListArray m_aLists; + + ~OAttribListMerger() { } + + public: + OAttribListMerger() { } + + // attribute list handling + // (very thinn at the moment ... only adding lists is allowed ... add more if you need it :) + void addList(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rList); + + // XAttributeList + virtual sal_Int16 SAL_CALL getLength( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getNameByIndex( sal_Int16 i ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTypeByIndex( sal_Int16 i ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTypeByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getValueByIndex( sal_Int16 i ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getValueByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + + protected: + sal_Bool seekToIndex(sal_Int16 _nGlobalIndex, ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rSubList, sal_Int16& _rLocalIndex); + sal_Bool seekToName(const ::rtl::OUString& _rName, ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rSubList, sal_Int16& _rLocalIndex); + }; + + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_ATTRIBLISTMERGE_HXX_ + diff --git a/xmloff/source/forms/callbacks.hxx b/xmloff/source/forms/callbacks.hxx new file mode 100644 index 000000000000..d0013220bddb --- /dev/null +++ b/xmloff/source/forms/callbacks.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_CALLBACKS_HXX_ +#define _XMLOFF_FORMS_CALLBACKS_HXX_ + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <vos/ref.hxx> + +class SvXMLImport; +class SvXMLExport; +class SvXMLExportPropertyMapper; +class SvXMLStyleContext; + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + class OAttribute2Property; + + //===================================================================== + //= IFormsExportContext + //===================================================================== + class IFormsExportContext + { + public: + virtual SvXMLExport& getGlobalContext() = 0; + virtual ::vos::ORef< SvXMLExportPropertyMapper > getStylePropertyMapper() = 0; + + /** steps through a collection and exports all children of this collection + */ + virtual void exportCollectionElements( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& _rxCollection) = 0; + + virtual ::rtl::OUString getObjectStyleName( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject ) = 0; + }; + + //===================================================================== + //= IEventAttacherManager + //===================================================================== + class IEventAttacherManager + { + public: + virtual void registerEvents( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxElement, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ) = 0; + }; + + //===================================================================== + //= IEventAttacher + //===================================================================== + class IEventAttacher + { + public: + virtual void registerEvents( + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ) = 0; + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_CALLBACKS_HXX_ + diff --git a/xmloff/source/forms/controlelement.cxx b/xmloff/source/forms/controlelement.cxx new file mode 100644 index 000000000000..84a74fe44a8b --- /dev/null +++ b/xmloff/source/forms/controlelement.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "controlelement.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OControlElement + //===================================================================== + //--------------------------------------------------------------------- + const sal_Char* OControlElement::getElementName(ElementType _eType) + { + switch (_eType) + { + case TEXT: return "text"; + case TEXT_AREA: return "textarea"; + case PASSWORD: return "password"; + case FILE: return "file"; + case FORMATTED_TEXT: return "formatted-text"; + case FIXED_TEXT: return "fixed-text"; + case COMBOBOX: return "combobox"; + case LISTBOX: return "listbox"; + case BUTTON: return "button"; + case IMAGE: return "image"; + case CHECKBOX: return "checkbox"; + case RADIO: return "radio"; + case FRAME: return "frame"; + case IMAGE_FRAME: return "image-frame"; + case HIDDEN: return "hidden"; + case GRID: return "grid"; + case VALUERANGE: return "value-range"; + + default: return "generic-control"; + } + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/controlelement.hxx b/xmloff/source/forms/controlelement.hxx new file mode 100644 index 000000000000..1816710fb4dc --- /dev/null +++ b/xmloff/source/forms/controlelement.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_CONTROLELEMENT_HXX_ +#define _XMLOFF_FORMS_CONTROLELEMENT_HXX_ + +#include <sal/types.h> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OControlElement + //===================================================================== + /** helper for translating between control types and XML tags + */ + class OControlElement + { + public: + enum ElementType + { + TEXT = 0, + TEXT_AREA, + PASSWORD, + FILE, + FORMATTED_TEXT, + FIXED_TEXT, + COMBOBOX, + LISTBOX, + BUTTON, + IMAGE, + CHECKBOX, + RADIO, + FRAME, + IMAGE_FRAME, + HIDDEN, + GRID, + VALUERANGE, + GENERIC_CONTROL, + + UNKNOWN // must be the last element + }; + + protected: + /** ctor. + <p>This default constructor is protected, 'cause this class is not intended to be instantiated + directly. Instead, the derived classes should be used.</p> + */ + OControlElement() { } + + public: + /** retrieves the tag name to be used to describe a control of the given type + + <p>The retuned string is the pure element name, without any namespace.</p> + + @param _eType + the element type + */ + static const sal_Char* getElementName(ElementType _eType); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_CONTROLELEMENT_HXX_ + diff --git a/xmloff/source/forms/controlpropertyhdl.cxx b/xmloff/source/forms/controlpropertyhdl.cxx new file mode 100644 index 000000000000..1cc5e5442764 --- /dev/null +++ b/xmloff/source/forms/controlpropertyhdl.cxx @@ -0,0 +1,390 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include <xmloff/controlpropertyhdl.hxx> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/awt/FontWidth.hpp> +#include <com/sun/star/awt/FontEmphasisMark.hpp> +#include <xmloff/xmltypes.hxx> +#include "xmloff/NamedBoolPropertyHdl.hxx" +#include "formenums.hxx" +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmltoken.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include "callbacks.hxx" +#include <xmloff/XMLConstantsPropertyHandler.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::beans; + using namespace ::xmloff::token; + + //===================================================================== + //= OControlPropertyHandlerFactory + //===================================================================== + //--------------------------------------------------------------------- + OControlPropertyHandlerFactory::OControlPropertyHandlerFactory() + :m_pTextAlignHandler(NULL) + ,m_pControlBorderStyleHandler(NULL) + ,m_pControlBorderColorHandler(NULL) + ,m_pRotationAngleHandler(NULL) + ,m_pFontWidthHandler(NULL) + ,m_pFontEmphasisHandler(NULL) + ,m_pFontReliefHandler(NULL) + { + } + + //--------------------------------------------------------------------- + OControlPropertyHandlerFactory::~OControlPropertyHandlerFactory() + { + delete m_pTextAlignHandler; + delete m_pControlBorderStyleHandler; + delete m_pControlBorderColorHandler; + delete m_pRotationAngleHandler; + delete m_pFontWidthHandler; + delete m_pFontEmphasisHandler; + delete m_pFontReliefHandler; + } + + //--------------------------------------------------------------------- + const XMLPropertyHandler* OControlPropertyHandlerFactory::GetPropertyHandler(sal_Int32 _nType) const + { + const XMLPropertyHandler* pHandler = NULL; + + switch (_nType) + { + case XML_TYPE_TEXT_ALIGN: + if (!m_pTextAlignHandler) + m_pTextAlignHandler = new XMLConstantsPropertyHandler(OEnumMapper::getEnumMap(OEnumMapper::epTextAlign), XML_TOKEN_INVALID ); + pHandler = m_pTextAlignHandler; + break; + + case XML_TYPE_CONTROL_BORDER: + if (!m_pControlBorderStyleHandler) + m_pControlBorderStyleHandler = new OControlBorderHandler( OControlBorderHandler::STYLE ); + pHandler = m_pControlBorderStyleHandler; + break; + + case XML_TYPE_CONTROL_BORDER_COLOR: + if ( !m_pControlBorderColorHandler ) + m_pControlBorderColorHandler = new OControlBorderHandler( OControlBorderHandler::COLOR ); + pHandler = m_pControlBorderColorHandler; + break; + + case XML_TYPE_ROTATION_ANGLE: + if (!m_pRotationAngleHandler) + m_pRotationAngleHandler = new ORotationAngleHandler; + pHandler = m_pRotationAngleHandler; + break; + + case XML_TYPE_FONT_WIDTH: + if (!m_pFontWidthHandler) + m_pFontWidthHandler = new OFontWidthHandler; + pHandler = m_pFontWidthHandler; + break; + + case XML_TYPE_CONTROL_TEXT_EMPHASIZE: + if (!m_pFontEmphasisHandler) + m_pFontEmphasisHandler = new XMLConstantsPropertyHandler( OEnumMapper::getEnumMap(OEnumMapper::epFontEmphasis), XML_NONE ); + pHandler = m_pFontEmphasisHandler; + break; + + case XML_TYPE_TEXT_FONT_RELIEF: + if (!m_pFontReliefHandler) + m_pFontReliefHandler = new XMLConstantsPropertyHandler( OEnumMapper::getEnumMap(OEnumMapper::epFontRelief), XML_NONE ); + pHandler = m_pFontReliefHandler; + break; + case XML_TYPE_TEXT_LINE_MODE: + pHandler = new XMLNamedBoolPropertyHdl( + ::xmloff::token::XML_SKIP_WHITE_SPACE, + ::xmloff::token::XML_CONTINUOUS); + break; + } + + if (!pHandler) + pHandler = XMLPropertyHandlerFactory::GetPropertyHandler(_nType); + return pHandler; + } + + //===================================================================== + //= OControlTextEmphasisHandler + //===================================================================== + OControlTextEmphasisHandler::OControlTextEmphasisHandler() + { + } + + //--------------------------------------------------------------------- + sal_Bool OControlTextEmphasisHandler::exportXML( ::rtl::OUString& _rStrExpValue, const Any& _rValue, const SvXMLUnitConverter& ) const + { + ::rtl::OUStringBuffer aReturn; + sal_Bool bSuccess = sal_False; + sal_Int16 nFontEmphasis = sal_Int16(); + if (_rValue >>= nFontEmphasis) + { + // the type + sal_Int16 nType = nFontEmphasis & ~(FontEmphasisMark::ABOVE | FontEmphasisMark::BELOW); + // the position of the mark + sal_Bool bBelow = 0 != (nFontEmphasis & FontEmphasisMark::BELOW); + + // convert + bSuccess = SvXMLUnitConverter::convertEnum(aReturn, nType, OEnumMapper::getEnumMap(OEnumMapper::epFontEmphasis), XML_NONE); + if (bSuccess) + { + aReturn.append( (sal_Unicode)' ' ); + aReturn.append( GetXMLToken(bBelow ? XML_BELOW : XML_ABOVE) ); + + _rStrExpValue = aReturn.makeStringAndClear(); + } + } + + return bSuccess; + } + + //--------------------------------------------------------------------- + sal_Bool OControlTextEmphasisHandler::importXML( const ::rtl::OUString& _rStrImpValue, Any& _rValue, const SvXMLUnitConverter& ) const + { + sal_Bool bSuccess = sal_True; + sal_uInt16 nEmphasis = FontEmphasisMark::NONE; + + sal_Bool bBelow = sal_False; + sal_Bool bHasPos = sal_False, bHasType = sal_False; + + ::rtl::OUString sToken; + SvXMLTokenEnumerator aTokenEnum(_rStrImpValue); + while (aTokenEnum.getNextToken(sToken)) + { + if (!bHasPos) + { + if (IsXMLToken(sToken, XML_ABOVE)) + { + bBelow = sal_False; + bHasPos = sal_True; + } + else if (IsXMLToken(sToken, XML_BELOW)) + { + bBelow = sal_True; + bHasPos = sal_True; + } + } + if (!bHasType) + { + if (SvXMLUnitConverter::convertEnum(nEmphasis, sToken, OEnumMapper::getEnumMap(OEnumMapper::epFontEmphasis))) + { + bHasType = sal_True; + } + else + { + bSuccess = sal_False; + break; + } + } + } + + if (bSuccess) + { + nEmphasis |= bBelow ? FontEmphasisMark::BELOW : FontEmphasisMark::ABOVE; + _rValue <<= (sal_Int16)nEmphasis; + } + + return bSuccess; + } + + //===================================================================== + //= OControlBorderHandlerBase + //===================================================================== + //--------------------------------------------------------------------- + OControlBorderHandler::OControlBorderHandler( const OControlBorderHandler::BorderFacet _eFacet ) + :m_eFacet( _eFacet ) + { + } + + //--------------------------------------------------------------------- + sal_Bool OControlBorderHandler::importXML( const ::rtl::OUString& _rStrImpValue, Any& _rValue, const SvXMLUnitConverter& ) const + { + ::rtl::OUString sToken; + SvXMLTokenEnumerator aTokens(_rStrImpValue); + + sal_uInt16 nStyle = 1; + Color aColor; + + while ( aTokens.getNextToken(sToken) // have a new token + && (0 != sToken.getLength()) // really have a new token + ) + { + // try interpreting the token as border style + if ( m_eFacet == STYLE ) + { + // is it a valid enum value? + if ( SvXMLUnitConverter::convertEnum( nStyle, sToken, OEnumMapper::getEnumMap( OEnumMapper::epBorderWidth ) ) ) + { + _rValue <<= nStyle; + return sal_True; + } + } + + // try interpreting it as color value + if ( m_eFacet == COLOR ) + { + if ( SvXMLUnitConverter::convertColor( aColor, sToken ) ) + { + _rValue <<= (sal_Int32)aColor.GetColor(); + return sal_True; + } + } + } + + return sal_False; + } + + //--------------------------------------------------------------------- + sal_Bool OControlBorderHandler::exportXML( ::rtl::OUString& _rStrExpValue, const Any& _rValue, const SvXMLUnitConverter& ) const + { + sal_Bool bSuccess = sal_False; + + ::rtl::OUStringBuffer aOut; + switch ( m_eFacet ) + { + case STYLE: + { + sal_Int16 nBorder = 0; + bSuccess = (_rValue >>= nBorder) + && SvXMLUnitConverter::convertEnum( aOut, nBorder, OEnumMapper::getEnumMap( OEnumMapper::epBorderWidth ) ); + } + break; + case COLOR: + { + sal_Int32 nBorderColor = 0; + if ( _rValue >>= nBorderColor ) + { + SvXMLUnitConverter::convertColor( aOut, Color( nBorderColor ) ); + bSuccess = sal_True; + } + } + break; + } // switch ( m_eFacet ) + + if ( !bSuccess ) + return sal_False; + + if ( _rStrExpValue.getLength() ) + _rStrExpValue += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ); + _rStrExpValue += aOut.makeStringAndClear(); + + return sal_True; + } + + //===================================================================== + //= OFontWidthHandler + //===================================================================== + //--------------------------------------------------------------------- + OFontWidthHandler::OFontWidthHandler() + { + } + + //--------------------------------------------------------------------- + sal_Bool OFontWidthHandler::importXML( const ::rtl::OUString& _rStrImpValue, Any& _rValue, const SvXMLUnitConverter& ) const + { + sal_Int32 nWidth = 0; + sal_Bool bSuccess = SvXMLUnitConverter::convertMeasure(nWidth, _rStrImpValue, MAP_POINT); + if (bSuccess) + _rValue <<= (sal_Int16)nWidth; + + return bSuccess; + } + + //--------------------------------------------------------------------- + sal_Bool OFontWidthHandler::exportXML( ::rtl::OUString& _rStrExpValue, const Any& _rValue, const SvXMLUnitConverter& ) const + { + sal_Int16 nWidth = 0; + ::rtl::OUStringBuffer aResult; + if (_rValue >>= nWidth) + SvXMLUnitConverter::convertMeasure(aResult, nWidth, MAP_POINT, MAP_POINT); + _rStrExpValue = aResult.makeStringAndClear(); + + return _rStrExpValue.getLength() != 0; + } + + //===================================================================== + //= ORotationAngleHandler + //===================================================================== + //--------------------------------------------------------------------- + ORotationAngleHandler::ORotationAngleHandler() + { + } + + //--------------------------------------------------------------------- + sal_Bool ORotationAngleHandler::importXML( const ::rtl::OUString& _rStrImpValue, Any& _rValue, const SvXMLUnitConverter& ) const + { + double fValue; + sal_Bool bSucces = + SvXMLUnitConverter::convertDouble(fValue, _rStrImpValue); + if (bSucces) + { + fValue *= 10; + _rValue <<= (float)fValue; + } + + return bSucces; + } + + //--------------------------------------------------------------------- + sal_Bool ORotationAngleHandler::exportXML( ::rtl::OUString& _rStrExpValue, const Any& _rValue, const SvXMLUnitConverter& ) const + { + float fAngle = 0; + sal_Bool bSuccess = (_rValue >>= fAngle); + + if (bSuccess) + { + rtl::OUStringBuffer sValue; + SvXMLUnitConverter::convertDouble(sValue, ((double)fAngle) / 10); + _rStrExpValue = sValue.makeStringAndClear(); + } + + return bSuccess; + } + + //===================================================================== + //= ImageScaleModeHandler + //===================================================================== + //--------------------------------------------------------------------- + ImageScaleModeHandler::ImageScaleModeHandler() + :XMLConstantsPropertyHandler( OEnumMapper::getEnumMap( OEnumMapper::epImageScaleMode ), XML_STRETCH ) + { + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/controlpropertymap.cxx b/xmloff/source/forms/controlpropertymap.cxx new file mode 100644 index 000000000000..8e81c2a7e19c --- /dev/null +++ b/xmloff/source/forms/controlpropertymap.cxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "xmlnmspe.hxx" +#include <xmloff/xmltoken.hxx> +#include <xmloff/maptype.hxx> +#include <xmloff/xmltypes.hxx> +#ifndef __SGI_STL_ALGORITHM +#include <algorithm> +#endif +#include "strings.hxx" +#include <xmloff/contextid.hxx> +#include "controlpropertymap.hxx" + +#include <string.h> + +using namespace ::xmloff::token; + +//......................................................................... +namespace xmloff +{ +//......................................................................... + +#define MAP_ASCII( name, prefix, token, type, context ) { name, sizeof(name)-1, prefix, token, type|XML_TYPE_PROP_TEXT, context, SvtSaveOptions::ODFVER_010 } +#define MAP_CONST( name, prefix, token, type, context ) { name.ascii, name.length, prefix, token, type|XML_TYPE_PROP_TEXT, context, SvtSaveOptions::ODFVER_010 } +#define MAP_CONST_P( name, prefix, token, type, context ) { name.ascii, name.length, prefix, token, type|XML_TYPE_PROP_PARAGRAPH, context, SvtSaveOptions::ODFVER_010 } +#define MAP_END() { NULL, 0, 0, XML_TOKEN_INVALID, 0, 0, SvtSaveOptions::ODFVER_010 } + + XMLPropertyMapEntry* getControlStylePropertyMap_Access( ) + { + static XMLPropertyMapEntry aControlStyleProperties[] = + { + MAP_CONST( PROPERTY_BACKGROUNDCOLOR, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLOR, 0 ), + MAP_CONST_P( PROPERTY_ALIGN, XML_NAMESPACE_FO, XML_TEXT_ALIGN, XML_TYPE_TEXT_ALIGN, 0 ), + MAP_CONST( PROPERTY_BORDER, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_CONTROL_BORDER|MID_FLAG_MULTI_PROPERTY|MID_FLAG_MERGE_ATTRIBUTE, 0 ), + MAP_ASCII( "FontCharWidth", XML_NAMESPACE_STYLE, XML_FONT_CHAR_WIDTH, XML_TYPE_NUMBER16, 0 ), + MAP_ASCII( "FontCharset", XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TYPE_TEXT_FONTENCODING, 0 ), + MAP_ASCII( "FontFamily", XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TYPE_TEXT_FONTFAMILY, 0 ), + MAP_ASCII( "FontHeight", XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT, 0 ), + MAP_ASCII( "FontKerning", XML_NAMESPACE_STYLE, XML_LETTER_KERNING, XML_TYPE_BOOL, 0 ), + MAP_ASCII( "FontName", XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TYPE_STRING, 0 ), + MAP_ASCII( "FontOrientation", XML_NAMESPACE_STYLE, XML_ROTATION_ANGLE, XML_TYPE_ROTATION_ANGLE, 0 ), + MAP_ASCII( "FontPitch", XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TYPE_TEXT_FONTPITCH, 0 ), + MAP_ASCII( "FontSlant", XML_NAMESPACE_FO, XML_FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ), + + MAP_ASCII( "FontStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_STYLE, XML_TYPE_TEXT_CROSSEDOUT_STYLE|MID_FLAG_MERGE_PROPERTY, 0), + MAP_ASCII( "FontStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TYPE, XML_TYPE_TEXT_CROSSEDOUT_TYPE|MID_FLAG_MERGE_PROPERTY, 0), + MAP_ASCII( "FontStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_WIDTH, XML_TYPE_TEXT_CROSSEDOUT_WIDTH|MID_FLAG_MERGE_PROPERTY, 0), + MAP_ASCII( "FontStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TEXT, XML_TYPE_TEXT_CROSSEDOUT_TEXT|MID_FLAG_MERGE_PROPERTY, 0), + + MAP_ASCII( "FontStyleName", XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TYPE_STRING, 0 ), + MAP_ASCII( "FontUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE, XML_TYPE_TEXT_UNDERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ), + MAP_ASCII( "FontUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_TYPE, XML_TYPE_TEXT_UNDERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ), + MAP_ASCII( "FontUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_WIDTH, XML_TYPE_TEXT_UNDERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ), + MAP_ASCII( "FontWeight", XML_NAMESPACE_FO, XML_FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ), + MAP_ASCII( "FontWidth", XML_NAMESPACE_STYLE, XML_FONT_WIDTH, XML_TYPE_FONT_WIDTH, 0 ), + MAP_ASCII( "FontWordLineMode", XML_NAMESPACE_FO, XML_SCORE_SPACES, XML_TYPE_NBOOL, 0 ), + MAP_ASCII( "SymbolColor", XML_NAMESPACE_STYLE, XML_COLOR, XML_TYPE_COLOR, 0 ), + MAP_ASCII( "BorderColor", XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_CONTROL_BORDER_COLOR|MID_FLAG_MULTI_PROPERTY|MID_FLAG_MERGE_ATTRIBUTE, 0 ), + MAP_ASCII( "TextColor", XML_NAMESPACE_FO, XML_COLOR, XML_TYPE_COLOR, 0 ), + MAP_CONST( PROPERTY_FORMATKEY, XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, XML_TYPE_STRING | MID_FLAG_NO_PROPERTY_EXPORT | MID_FLAG_SPECIAL_ITEM, CTF_FORMS_DATA_STYLE ), + MAP_ASCII( "FontEmphasisMark", XML_NAMESPACE_STYLE, XML_TEXT_EMPHASIZE, XML_TYPE_CONTROL_TEXT_EMPHASIZE, 0 ), + MAP_ASCII( "FontRelief", XML_NAMESPACE_STYLE, XML_FONT_RELIEF, XML_TYPE_TEXT_FONT_RELIEF|MID_FLAG_MULTI_PROPERTY, 0 ), + MAP_ASCII( "TextLineColor", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, 0 ), + MAP_END() + }; + + return aControlStyleProperties; + } + + const XMLPropertyMapEntry* getControlStylePropertyMap( ) + { + return getControlStylePropertyMap_Access(); + } + + //===================================================================== + //--------------------------------------------------------------------- + struct XMLPropertyMapEntryLess + { + sal_Bool operator()(const XMLPropertyMapEntry& _rLeft, const XMLPropertyMapEntry& _rRight) + { + return strcmp(_rLeft.msApiName, _rRight.msApiName) < 0; + } + }; + + //--------------------------------------------------------------------- + void implSortMap(XMLPropertyMapEntry* _pMap) + { + XMLPropertyMapEntry* pEnd; + // determine the last element + for ( pEnd = _pMap; pEnd->msApiName; ++pEnd) + ; + ::std::sort(_pMap, pEnd, XMLPropertyMapEntryLess()); + } + + //--------------------------------------------------------------------- + void initializePropertyMaps() + { + static sal_Bool bSorted = sal_False; + if (!bSorted) + { + implSortMap(getControlStylePropertyMap_Access()); + bSorted = sal_True; + } + } + + //===================================================================== + //= OFormComponentStyleExportMapper + //===================================================================== + //--------------------------------------------------------------------- + OFormComponentStyleExportMapper::OFormComponentStyleExportMapper( const UniReference< XMLPropertySetMapper >& _rMapper ) + :SvXMLExportPropertyMapper( _rMapper ) + { + } + + //--------------------------------------------------------------------- + void OFormComponentStyleExportMapper::handleSpecialItem( SvXMLAttributeList& _rAttrList, const XMLPropertyState& _rProperty, const SvXMLUnitConverter& _rUnitConverter, + const SvXMLNamespaceMap& _rNamespaceMap, const ::std::vector< XMLPropertyState >* _pProperties, + sal_uInt32 _nIdx ) const + { + // ignore the number style of grid columns - this is formatted elsewhere + if ( CTF_FORMS_DATA_STYLE != getPropertySetMapper()->GetEntryContextId( _rProperty.mnIndex ) ) + SvXMLExportPropertyMapper::handleSpecialItem( _rAttrList, _rProperty, _rUnitConverter, _rNamespaceMap, _pProperties, _nIdx ); + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/controlpropertymap.hxx b/xmloff/source/forms/controlpropertymap.hxx new file mode 100644 index 000000000000..35201a76d190 --- /dev/null +++ b/xmloff/source/forms/controlpropertymap.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_CONTROLPROPERTYMAP_HXX_ +#define _XMLOFF_FORMS_CONTROLPROPERTYMAP_HXX_ + +#include <xmloff/xmlprmap.hxx> +#include <xmloff/xmlexppr.hxx> + +struct XMLPropertyMapEntry; +//......................................................................... +namespace xmloff +{ +//......................................................................... + + const XMLPropertyMapEntry* getControlStylePropertyMap( ); + + void initializePropertyMaps(); + + //===================================================================== + //= OFormComponentStyleExportMapper + //===================================================================== + class OFormComponentStyleExportMapper : public SvXMLExportPropertyMapper + { + public: + OFormComponentStyleExportMapper( const UniReference< XMLPropertySetMapper >& _rMapper ); + + void handleSpecialItem( + SvXMLAttributeList& _rAttrList, + const XMLPropertyState& _rProperty, + const SvXMLUnitConverter& _rUnitConverter, + const SvXMLNamespaceMap& _rNamespaceMap, + const ::std::vector< XMLPropertyState >* _pProperties, + sal_uInt32 _nIdx + ) const; + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_CONTROLPROPERTYMAP_HXX_ + + diff --git a/xmloff/source/forms/elementexport.cxx b/xmloff/source/forms/elementexport.cxx new file mode 100644 index 000000000000..9baf402e5ea7 --- /dev/null +++ b/xmloff/source/forms/elementexport.cxx @@ -0,0 +1,2152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include "elementexport.hxx" +#include "strings.hxx" +#include "xmlnmspe.hxx" +#include "eventexport.hxx" +#include "formenums.hxx" +#include "formcellbinding.hxx" +#include "formcellbinding.hxx" +#include "xformsexport.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/form/FormSubmitEncoding.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/form/NavigationBarMode.hpp> +#include <com/sun/star/form/TabulatorCycle.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/awt/VisualEffect.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/ImagePosition.hpp> +/** === end UNO includes === **/ + +#include <tools/wintypes.hxx> // for check states +#include <xmloff/txtprmap.hxx> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <tools/urlobj.hxx> +#include <xmloff/xmlexp.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/XMLEventExport.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmltoken.hxx> +#include <tools/time.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/extract.hxx> + +#include <stdio.h> +#include <algorithm> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + #if OSL_DEBUG_LEVEL > 0 + #define RESET_BIT( bitfield, bit ) \ + bitfield = bitfield & ~bit + #else + #define RESET_BIT( bitfield, bit ) + #endif + + using namespace ::xmloff::token; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::script; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::table; + using namespace ::com::sun::star::text; + using namespace ::com::sun::star::form::binding; + + //===================================================================== + //= OElementExport + //===================================================================== + OElementExport::OElementExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxProps, + const Sequence< ScriptEventDescriptor >& _rEvents) + :OPropertyExport(_rContext, _rxProps) + ,m_aEvents(_rEvents) + ,m_pXMLElement(NULL) + { + } + + //--------------------------------------------------------------------- + OElementExport::~OElementExport() + { + implEndElement(); + } + + //--------------------------------------------------------------------- + void OElementExport::doExport() + { + // collect some general information about the element + examine(); + + // first add the attributes necessary for the element + m_rContext.getGlobalContext().ClearAttrList(); + + // add the attributes + exportAttributes(); + + // start the XML element + implStartElement(getXMLElementName()); + + // the sub elements (mostly control type dependent) + exportSubTags(); + + implEndElement(); + } + + //--------------------------------------------------------------------- + void OElementExport::examine() + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OElementExport::exportAttributes() + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OElementExport::exportSubTags() + { + // the properties which where not exported 'til now + exportRemainingProperties(); + + // the script:events sub tags + exportEvents(); + } + + //--------------------------------------------------------------------- + void OElementExport::implStartElement(const sal_Char* _pName) + { + m_pXMLElement = new SvXMLElementExport(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, _pName, sal_True, sal_True); + } + + //--------------------------------------------------------------------- + void OElementExport::implEndElement() + { + delete m_pXMLElement; + m_pXMLElement = NULL; + } + + //--------------------------------------------------------------------- + void OElementExport::exportServiceNameAttribute() + { + Reference< XPersistObject > xPersistence(m_xProps, UNO_QUERY); + if (!xPersistence.is()) + { + OSL_ENSURE(sal_False, "OElementExport::exportServiceNameAttribute: no XPersistObject!"); + return; + } + + ::rtl::OUString sServiceName = xPersistence->getServiceName(); + // we don't want to write the old service name directly: it's a name used for compatibility reasons, but + // as we start some kind of new file format here (with this xml export), we don't care about + // compatibility ... + // So we translate the old persistence service name into new ones, if possible + + ::rtl::OUString sToWriteServiceName = sServiceName; +#define CHECK_N_TRANSLATE( name ) \ + else if (0 == sServiceName.compareToAscii(SERVICE_PERSISTENT_COMPONENT_##name)) \ + sToWriteServiceName = SERVICE_##name + + if (sal_False) + ; + CHECK_N_TRANSLATE( FORM ); + CHECK_N_TRANSLATE( FORM ); + CHECK_N_TRANSLATE( LISTBOX ); + CHECK_N_TRANSLATE( COMBOBOX ); + CHECK_N_TRANSLATE( RADIOBUTTON ); + CHECK_N_TRANSLATE( GROUPBOX ); + CHECK_N_TRANSLATE( FIXEDTEXT ); + CHECK_N_TRANSLATE( COMMANDBUTTON ); + CHECK_N_TRANSLATE( CHECKBOX ); + CHECK_N_TRANSLATE( GRID ); + CHECK_N_TRANSLATE( IMAGEBUTTON ); + CHECK_N_TRANSLATE( FILECONTROL ); + CHECK_N_TRANSLATE( TIMEFIELD ); + CHECK_N_TRANSLATE( DATEFIELD ); + CHECK_N_TRANSLATE( NUMERICFIELD ); + CHECK_N_TRANSLATE( CURRENCYFIELD ); + CHECK_N_TRANSLATE( PATTERNFIELD ); + CHECK_N_TRANSLATE( HIDDENCONTROL ); + CHECK_N_TRANSLATE( IMAGECONTROL ); + CHECK_N_TRANSLATE( FORMATTEDFIELD ); + else if (0 == sServiceName.compareToAscii(SERVICE_PERSISTENT_COMPONENT_EDIT)) + { // special handling for the edit field: we have two controls using this as persistence service name + sToWriteServiceName = SERVICE_EDIT; + Reference< XServiceInfo > xSI(m_xProps, UNO_QUERY); + if (xSI.is() && xSI->supportsService(SERVICE_FORMATTEDFIELD)) + sToWriteServiceName = SERVICE_FORMATTEDFIELD; + } +#if OSL_DEBUG_LEVEL > 0 + Reference< XServiceInfo > xSI(m_xProps, UNO_QUERY); + OSL_ENSURE(xSI.is() && xSI->supportsService(sToWriteServiceName), + "OElementExport::exportServiceNameAttribute: wrong service name translation!"); + +#endif + sToWriteServiceName = + m_rContext.getGlobalContext().GetNamespaceMap().GetQNameByKey( + XML_NAMESPACE_OOO, sToWriteServiceName ); + + // now write this + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_SERVICE_NAME), + OAttributeMetaData::getCommonControlAttributeName(CCA_SERVICE_NAME), + sToWriteServiceName); + } + + //--------------------------------------------------------------------- + void OElementExport::exportEvents() + { + if (!m_aEvents.getLength()) + // nothing to do + return; + + Reference< XNameReplace > xWrapper = new OEventDescriptorMapper(m_aEvents); + m_rContext.getGlobalContext().GetEventExport().Export(xWrapper); + } + + //===================================================================== + //= OControlExport + //===================================================================== + //--------------------------------------------------------------------- + OControlExport::OControlExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxControl, + const ::rtl::OUString& _rControlId, const ::rtl::OUString& _rReferringControls, + const Sequence< ScriptEventDescriptor >& _rEvents) + :OElementExport(_rContext, _rxControl, _rEvents) + ,m_sControlId(_rControlId) + ,m_sReferringControls(_rReferringControls) + ,m_nClassId(FormComponentType::CONTROL) + ,m_eType( UNKNOWN ) + ,m_nIncludeCommon(0) + ,m_nIncludeDatabase(0) + ,m_nIncludeSpecial(0) + ,m_nIncludeEvents(0) + ,m_nIncludeBindings(0) + ,m_pOuterElement(NULL) + { + OSL_ENSURE(m_xProps.is(), "OControlExport::OControlExport: invalid arguments!"); + } + + //--------------------------------------------------------------------- + OControlExport::~OControlExport() + { + implEndElement(); + } + + //--------------------------------------------------------------------- + void OControlExport::exportOuterAttributes() + { + // the control id + if (CCA_NAME & m_nIncludeCommon) + { + exportStringPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_NAME), + OAttributeMetaData::getCommonControlAttributeName(CCA_NAME), + PROPERTY_NAME + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_NAME; + #endif + } + + // the service name + if (m_nIncludeCommon & CCA_SERVICE_NAME) + { + exportServiceNameAttribute(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_SERVICE_NAME; + #endif + } + } + + //--------------------------------------------------------------------- + void OControlExport::exportInnerAttributes() + { + // the control id + if (CCA_CONTROL_ID & m_nIncludeCommon) + { + OSL_ENSURE(m_sControlId.getLength(), "OControlExport::exportInnerAttributes: have no control id for the control!"); + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_CONTROL_ID), + OAttributeMetaData::getCommonControlAttributeName(CCA_CONTROL_ID), + m_sControlId); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_CONTROL_ID; + #endif + } + + // common control attributes + exportCommonControlAttributes(); + + // common database attributes + exportDatabaseAttributes(); + + // attributes related to external bindings + exportBindingAtributes(); + + // attributes special to the respective control type + exportSpecialAttributes(); + + // add the style references to the attributes + flagStyleProperties(); + } + + //--------------------------------------------------------------------- + void OControlExport::exportAttributes() + { + exportOuterAttributes(); + } + + //--------------------------------------------------------------------- + void OControlExport::exportSubTags() throw (Exception) + { + // for the upcoming exportRemainingProperties: + // if a control has the LabelControl property, this is not stored with the control itself, but instead with + // the control which is referenced by this property. As the base class' exportRemainingProperties doesn't + // know anything about this, we need to prevent that it tries to export this property + exportedProperty(PROPERTY_CONTROLLABEL); + + // if it's a control supporting XText, then we need to declare all text-related properties + // as "already exported". This prevents them from being exported as generic "form:property"-tags. + // *If* we would export them this way, they would be completely superfluous, and sometimes even + // disastrous, since they may, at import time, override paragraph properties which already have + // been set before + Reference< XText > xControlText( m_xProps, UNO_QUERY ); + if ( xControlText.is() ) + { + const XMLPropertyMapEntry* pCharAttributeProperties = XMLTextPropertySetMapper::getPropertyMapForType( TEXT_PROP_MAP_TEXT ); + while ( pCharAttributeProperties->msApiName ) + { + exportedProperty( ::rtl::OUString::createFromAscii( pCharAttributeProperties->msApiName ) ); + ++pCharAttributeProperties; + } + + const XMLPropertyMapEntry* pParaAttributeProperties = XMLTextPropertySetMapper::getPropertyMapForType( TEXT_PROP_MAP_SHAPE_PARA ); + while ( pParaAttributeProperties->msApiName ) + { + exportedProperty( ::rtl::OUString::createFromAscii( pParaAttributeProperties->msApiName ) ); + ++pParaAttributeProperties; + } + + // the RichText property is not exported. The presence of the text:p element + // will be used - upon reading - as indicator for the value of the RichText property + exportedProperty( PROPERTY_RICH_TEXT ); + + // strange thing: paragraphs support both a CharStrikeout and a CharCrossedOut property + // The former is a short/enum value, the latter a boolean. The former has a real meaning + // (the strikeout type), the latter hasn't. But, when the CharCrossedOut is exported and + // later on imported, it overwrites anything which has previously been imported for + // CharStrikeout. + // 2004-04-14 - #i27729# - fs@openoffice.org + exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharCrossedOut" ) ) ); + } + + if ( m_eType == LISTBOX ) + { + // will be exported in exportListSourceAsElements: + if ( controlHasUserSuppliedListEntries() ) + exportedProperty( PROPERTY_DEFAULT_SELECT_SEQ ); + + // will not be exported in a generic way. Either exportListSourceAsElements cares + // for them, or we don't need them + exportedProperty( PROPERTY_STRING_ITEM_LIST ); + exportedProperty( PROPERTY_VALUE_SEQ ); + exportedProperty( PROPERTY_SELECT_SEQ ); + exportedProperty( PROPERTY_LISTSOURCE ); + } + if ( m_eType == COMBOBOX ) + exportedProperty( PROPERTY_STRING_ITEM_LIST ); + + // let the base class export the remaining properties and the events + OElementExport::exportSubTags(); + + // special sub tags for some controls + switch (m_eType) + { + case LISTBOX: + // don't export the list entries if the are not provided by the user, but obtained implicitly + // from other sources + // #i26944# - 2004-05-17 - fs@openoffice.org + if ( controlHasUserSuppliedListEntries() ) + exportListSourceAsElements(); + break; + case GRID: + { // a grid control requires us to store all columns as sub elements + Reference< XIndexAccess > xColumnContainer(m_xProps, UNO_QUERY); + OSL_ENSURE(xColumnContainer.is(), "OControlExport::exportSubTags: a grid control which is no IndexAccess?!!"); + if (xColumnContainer.is()) + m_rContext.exportCollectionElements(xColumnContainer); + } + break; + case COMBOBOX: + { // a combox box description has sub elements: the items + DBG_CHECK_PROPERTY( PROPERTY_STRING_ITEM_LIST, Sequence< ::rtl::OUString > ); + + // don't export the list entries if the are not provided by the user, but obtained implicitly + // from other sources + // #i26944# - 2004-05-17 - fs@openoffice.org + if ( controlHasUserSuppliedListEntries() ) + { + // get the item list + Sequence< ::rtl::OUString > aListItems; + m_xProps->getPropertyValue(PROPERTY_STRING_ITEM_LIST) >>= aListItems; + // loop through it and write the sub elements + const ::rtl::OUString* pListItems = aListItems.getConstArray(); + for (sal_Int32 i=0; i<aListItems.getLength(); ++i, ++pListItems) + { + m_rContext.getGlobalContext().ClearAttrList(); + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_LABEL), + OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL), + *pListItems); + SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "item", sal_True, sal_True); + } + } + } + break; + + case TEXT_AREA: + { + // if we act as rich text control, we need to export some text:p elements + if ( xControlText.is() ) + { + sal_Bool bActingAsRichText = sal_False; + if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_RICH_TEXT ) ) + { + OSL_VERIFY(m_xProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActingAsRichText ); + } + + if ( bActingAsRichText ) + m_rContext.getGlobalContext().GetTextParagraphExport()->exportText( xControlText ); + } + } + break; + default: + // nothing do to + break; + } + } + + //--------------------------------------------------------------------- + void OControlExport::exportCommonControlAttributes() + { + size_t i=0; + + // I decided to handle all the properties here with some static arrays describing the property-attribute + // relations. This leads to somewhat ugly code :), but the only alternative I can think of right now + // would require maps and O(log n) searches, which seems somewhat expensive as this code is used + // very frequently. + + // the extra indents for the respective blocks are to ensure that there is no copy'n'paste error, using + // map identifiers from the wrong block + + // -------------------------------------------------------------------- + // some string properties + { + // the attribute ids of all properties which are expected to be of type string + static sal_Int32 nStringPropertyAttributeIds[] = + { + CCA_LABEL, CCA_TITLE + }; + // the names of all properties which are expected to be of type string + static ::rtl::OUString aStringPropertyNames[] = + { + PROPERTY_LABEL, PROPERTY_TITLE + }; + OSL_ENSURE( sizeof(aStringPropertyNames)/sizeof(aStringPropertyNames[0]) == + sizeof(nStringPropertyAttributeIds)/sizeof(nStringPropertyAttributeIds[0]), + "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (1)!"); + + for (i=0; i<sizeof(nStringPropertyAttributeIds)/sizeof(nStringPropertyAttributeIds[0]); ++i) + if (nStringPropertyAttributeIds[i] & m_nIncludeCommon) + { + exportStringPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(nStringPropertyAttributeIds[i]), + OAttributeMetaData::getCommonControlAttributeName(nStringPropertyAttributeIds[i]), + aStringPropertyNames[i] + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~nStringPropertyAttributeIds[i]; + #endif + } + } + + // -------------------------------------------------------------------- + // some boolean properties + { + static sal_Int32 nBooleanPropertyAttributeIds[] = + { // attribute flags + CCA_CURRENT_SELECTED, CCA_DISABLED, CCA_DROPDOWN, CCA_PRINTABLE, CCA_READONLY, CCA_SELECTED, CCA_TAB_STOP, CCA_ENABLEVISIBLE + }; + static const ::rtl::OUString* pBooleanPropertyNames[] = + { // property names + &PROPERTY_STATE, &PROPERTY_ENABLED, &PROPERTY_DROPDOWN, &PROPERTY_PRINTABLE, &PROPERTY_READONLY, &PROPERTY_DEFAULT_STATE, &PROPERTY_TABSTOP, &PROPERTY_ENABLEVISIBLE + }; + static sal_Bool nBooleanPropertyAttrFlags[] = + { // attribute defaults + BOOLATTR_DEFAULT_FALSE, BOOLATTR_DEFAULT_FALSE | BOOLATTR_INVERSE_SEMANTICS, BOOLATTR_DEFAULT_FALSE, BOOLATTR_DEFAULT_TRUE, BOOLATTR_DEFAULT_FALSE, BOOLATTR_DEFAULT_FALSE, BOOLATTR_DEFAULT_VOID, BOOLATTR_DEFAULT_FALSE + }; + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nIdCount = sizeof(nBooleanPropertyAttributeIds) / sizeof(nBooleanPropertyAttributeIds[0]); + sal_Int32 nNameCount = sizeof(pBooleanPropertyNames) / sizeof(pBooleanPropertyNames[0]); + sal_Int32 nFlagsCount = sizeof(nBooleanPropertyAttrFlags) / sizeof(nBooleanPropertyAttrFlags[0]); + OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nFlagsCount), + "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (2)!"); + #endif + for (i=0; i<sizeof(nBooleanPropertyAttributeIds)/sizeof(nBooleanPropertyAttributeIds[0]); ++i) + if (nBooleanPropertyAttributeIds[i] & m_nIncludeCommon) + { + exportBooleanPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(nBooleanPropertyAttributeIds[i]), + OAttributeMetaData::getCommonControlAttributeName(nBooleanPropertyAttributeIds[i]), + *(pBooleanPropertyNames[i]), + nBooleanPropertyAttrFlags[i]); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~nBooleanPropertyAttributeIds[i]; + #endif + } + } + + + // -------------------------------------------------------------------- + // some integer properties + { + // now the common handling + static sal_Int32 nIntegerPropertyAttributeIds[] = + { // attribute flags + CCA_SIZE, CCA_TAB_INDEX + }; + static const ::rtl::OUString* pIntegerPropertyNames[] = + { // property names + &PROPERTY_LINECOUNT, &PROPERTY_TABINDEX + }; + static const sal_Int16 nIntegerPropertyAttrDefaults[] = + { // attribute defaults + 5, 0 + }; + + if ( m_nIncludeCommon & CCA_MAX_LENGTH ) + exportedProperty(PROPERTY_MAXTEXTLENGTH); + + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nIdCount = sizeof(nIntegerPropertyAttributeIds) / sizeof(nIntegerPropertyAttributeIds[0]); + sal_Int32 nNameCount = sizeof(pIntegerPropertyNames) / sizeof(pIntegerPropertyNames[0]); + sal_Int32 nDefaultCount = sizeof(nIntegerPropertyAttrDefaults) / sizeof(nIntegerPropertyAttrDefaults[0]); + OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nDefaultCount), + "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (3)!"); + #endif + for (i=0; i<sizeof(nIntegerPropertyAttributeIds)/sizeof(nIntegerPropertyAttributeIds[0]); ++i) + if (nIntegerPropertyAttributeIds[i] & m_nIncludeCommon) + { + exportInt16PropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(nIntegerPropertyAttributeIds[i]), + OAttributeMetaData::getCommonControlAttributeName(nIntegerPropertyAttributeIds[i]), + *(pIntegerPropertyNames[i]), + nIntegerPropertyAttrDefaults[i]); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~nIntegerPropertyAttributeIds[i]; + #endif + } + + + } + + // -------------------------------------------------------------------- + // some enum properties + { + if (m_nIncludeCommon & CCA_BUTTON_TYPE) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_BUTTON_TYPE), + OAttributeMetaData::getCommonControlAttributeName(CCA_BUTTON_TYPE), + PROPERTY_BUTTONTYPE, + OEnumMapper::getEnumMap(OEnumMapper::epButtonType), + FormButtonType_PUSH); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_BUTTON_TYPE; + #endif + } + if ( m_nIncludeCommon & CCA_ORIENTATION ) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace( CCA_ORIENTATION ), + OAttributeMetaData::getCommonControlAttributeName( CCA_ORIENTATION ), + PROPERTY_ORIENTATION, + OEnumMapper::getEnumMap( OEnumMapper::epOrientation ), + ScrollBarOrientation::HORIZONTAL + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_ORIENTATION; + #endif + } + + if ( m_nIncludeCommon & CCA_VISUAL_EFFECT ) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace( CCA_VISUAL_EFFECT ), + OAttributeMetaData::getCommonControlAttributeName( CCA_VISUAL_EFFECT ), + PROPERTY_VISUAL_EFFECT, + OEnumMapper::getEnumMap( OEnumMapper::epVisualEffect ), + VisualEffect::LOOK3D + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_VISUAL_EFFECT; + #endif + } + } + + // -------------------------------------------------------------------- + // some properties which require a special handling + + // the target frame + if (m_nIncludeCommon & CCA_TARGET_FRAME) + { + exportTargetFrameAttribute(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_TARGET_FRAME; + #endif + } + + // max text length + if ( m_nIncludeCommon & CCA_MAX_LENGTH ) + { + // normally, the respective property would be "MaxTextLen" + // However, if the model has a property "PersistenceMaxTextLength", then we prefer this + + // determine the name of the property to export + ::rtl::OUString sTextLenPropertyName( PROPERTY_MAXTEXTLENGTH ); + if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_PERSISTENCE_MAXTEXTLENGTH ) ) + sTextLenPropertyName = PROPERTY_PERSISTENCE_MAXTEXTLENGTH; + + // export it + exportInt16PropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace( CCA_MAX_LENGTH ), + OAttributeMetaData::getCommonControlAttributeName( CCA_MAX_LENGTH ), + sTextLenPropertyName, + 0 + ); + + // in either way, both properties count as "exported" + exportedProperty( PROPERTY_MAXTEXTLENGTH ); + exportedProperty( PROPERTY_PERSISTENCE_MAXTEXTLENGTH ); + + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_MAX_LENGTH; + #endif + } + + if (m_nIncludeCommon & CCA_TARGET_LOCATION) + { + exportTargetLocationAttribute(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_TARGET_LOCATION; + #endif + } + + // OJ #99721# + if (m_nIncludeCommon & CCA_IMAGE_DATA) + { + exportImageDataAttribute(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_IMAGE_DATA; + #endif + } + + // the for attribute + // the target frame + if (m_nIncludeCommon & CCA_FOR) + { + if (m_sReferringControls.getLength()) + { // there is at least one control referring to the one we're handling currently + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_FOR), + OAttributeMetaData::getCommonControlAttributeName(CCA_FOR), + m_sReferringControls); + } + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_FOR; + #endif + } + + if ((CCA_CURRENT_VALUE | CCA_VALUE) & m_nIncludeCommon) + { + const sal_Char* pCurrentValuePropertyName = NULL; + const sal_Char* pValuePropertyName = NULL; + + // get the property names + getValuePropertyNames(m_eType, m_nClassId, pCurrentValuePropertyName, pValuePropertyName); + + static const sal_Char* pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_VALUE); + static const sal_Char* pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_VALUE); + static const sal_uInt16 nCurrentValueAttributeNamespaceKey = OAttributeMetaData::getCommonControlAttributeNamespace(CCA_CURRENT_VALUE); + static const sal_uInt16 nValueAttributeNamespaceKey = OAttributeMetaData::getCommonControlAttributeNamespace(CCA_VALUE); + + // add the atrtributes if necessary and possible + if (pCurrentValuePropertyName && (CCA_CURRENT_VALUE & m_nIncludeCommon)) + { + // don't export the current-value if this value originates from a data binding + // #i26944# - 2004-05-17 - fs@openoffice.org + if ( controlHasActiveDataBinding() ) + exportedProperty( ::rtl::OUString::createFromAscii( pCurrentValuePropertyName ) ); + else + exportGenericPropertyAttribute( + nCurrentValueAttributeNamespaceKey, + pCurrentValueAttributeName, + pCurrentValuePropertyName + ); + } + + if (pValuePropertyName && (CCA_VALUE & m_nIncludeCommon)) + exportGenericPropertyAttribute( + nValueAttributeNamespaceKey, + pValueAttributeName, + pValuePropertyName); + + OSL_ENSURE((NULL == pValuePropertyName) == (0 == (CCA_VALUE & m_nIncludeCommon)), + "OControlExport::exportCommonControlAttributes: no property found for the value attribute!"); + OSL_ENSURE((NULL == pCurrentValuePropertyName ) == (0 == (CCA_CURRENT_VALUE & m_nIncludeCommon)), + "OControlExport::exportCommonControlAttributes: no property found for the current-value attribute!"); + + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~(CCA_CURRENT_VALUE | CCA_VALUE); + #endif + } + + OSL_ENSURE(0 == m_nIncludeCommon, + "OControlExport::exportCommonControlAttributes: forgot some flags!"); + // in the dbg_util version, we should have removed every bit we handled from the mask, so it should + // be 0 now ... + } + + //--------------------------------------------------------------------- + void OControlExport::exportDatabaseAttributes() + { +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nIncludeDatabase = m_nIncludeDatabase; +#endif + // the only string property: DataField + if (DA_DATA_FIELD & m_nIncludeDatabase) + { + exportStringPropertyAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace(DA_DATA_FIELD), + OAttributeMetaData::getDatabaseAttributeName(DA_DATA_FIELD), + PROPERTY_DATAFIELD); + RESET_BIT( nIncludeDatabase, DA_DATA_FIELD ); + } + + // InputRequired + if ( DA_INPUT_REQUIRED & m_nIncludeDatabase ) + { + exportBooleanPropertyAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace( DA_INPUT_REQUIRED ), + OAttributeMetaData::getDatabaseAttributeName( DA_INPUT_REQUIRED ), + PROPERTY_INPUT_REQUIRED, + BOOLATTR_DEFAULT_TRUE + ); + RESET_BIT( nIncludeDatabase, DA_INPUT_REQUIRED ); + } + + // the only int16 property: BoundColumn + if (DA_BOUND_COLUMN & m_nIncludeDatabase) + { + exportInt16PropertyAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace(DA_BOUND_COLUMN), + OAttributeMetaData::getDatabaseAttributeName(DA_BOUND_COLUMN), + PROPERTY_BOUNDCOLUMN, + 0); + RESET_BIT( nIncludeDatabase, DA_BOUND_COLUMN ); + } + + // ConvertEmptyToNull + if (DA_CONVERT_EMPTY & m_nIncludeDatabase) + { + exportBooleanPropertyAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace(DA_CONVERT_EMPTY), + OAttributeMetaData::getDatabaseAttributeName(DA_CONVERT_EMPTY), + PROPERTY_EMPTY_IS_NULL, + BOOLATTR_DEFAULT_FALSE + ); + RESET_BIT( nIncludeDatabase, DA_CONVERT_EMPTY ); + } + + // the only enum property: ListSourceType + if (DA_LIST_SOURCE_TYPE & m_nIncludeDatabase) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace(DA_LIST_SOURCE_TYPE), + OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE_TYPE), + PROPERTY_LISTSOURCETYPE, + OEnumMapper::getEnumMap(OEnumMapper::epListSourceType), + ListSourceType_VALUELIST + ); + RESET_BIT( nIncludeDatabase, DA_LIST_SOURCE_TYPE ); + } + + if (m_nIncludeDatabase & DA_LIST_SOURCE) + { + exportListSourceAsAttribute(); + RESET_BIT( nIncludeDatabase, DA_LIST_SOURCE ); + } + +#if OSL_DEBUG_LEVEL > 0 + OSL_ENSURE(0 == nIncludeDatabase, + "OControlExport::exportDatabaseAttributes: forgot some flags!"); + // in the dbg_util version, we should have removed every bit we handled from the mask, so it should + // be 0 now ... +#endif + } + + //--------------------------------------------------------------------- + void OControlExport::exportBindingAtributes() + { +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nIncludeBinding = m_nIncludeBindings; +#endif + + // .................................................... + if ( m_nIncludeBindings & BA_LINKED_CELL ) + { + exportCellBindingAttributes( ( m_nIncludeBindings & BA_LIST_LINKING_TYPE ) != 0 ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + nIncludeBinding = nIncludeBinding & ~( BA_LINKED_CELL | BA_LIST_LINKING_TYPE ); + #endif + } + + // .................................................... + if ( m_nIncludeBindings & BA_LIST_CELL_RANGE ) + { + exportCellListSourceRange(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + nIncludeBinding = nIncludeBinding & ~BA_LIST_CELL_RANGE; + #endif + } + + if ( m_nIncludeBindings & BA_XFORMS_BIND ) + { + exportXFormsBindAttributes(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + nIncludeBinding = nIncludeBinding & ~BA_XFORMS_BIND; + #endif + } + + if ( m_nIncludeBindings & BA_XFORMS_LISTBIND ) + { + exportXFormsListAttributes(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + nIncludeBinding = nIncludeBinding & ~BA_XFORMS_LISTBIND; + #endif + } + + if ( m_nIncludeBindings & BA_XFORMS_SUBMISSION ) + { + exportXFormsSubmissionAttributes(); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + nIncludeBinding = nIncludeBinding & ~BA_XFORMS_SUBMISSION; + #endif + } + + OSL_ENSURE( 0 == nIncludeBinding, + "OControlExport::exportBindingAtributes: forgot some flags!"); + // in the debug version, we should have removed every bit we handled from the mask, so it should + // be 0 now ... + } + + //--------------------------------------------------------------------- + void OControlExport::exportSpecialAttributes() + { + sal_Int32 i=0; + + // ---------------------- + // the boolean properties + { + static const sal_Int32 nBooleanPropertyAttributeIds[] = + { // attribute flags + SCA_VALIDATION, SCA_MULTI_LINE, SCA_AUTOMATIC_COMPLETION, SCA_MULTIPLE, SCA_DEFAULT_BUTTON, SCA_IS_TRISTATE, + SCA_TOGGLE, SCA_FOCUS_ON_CLICK + }; + static const ::rtl::OUString* pBooleanPropertyNames[] = + { // property names + &PROPERTY_STRICTFORMAT, &PROPERTY_MULTILINE, &PROPERTY_AUTOCOMPLETE, &PROPERTY_MULTISELECTION, &PROPERTY_DEFAULTBUTTON, &PROPERTY_TRISTATE, + &PROPERTY_TOGGLE, &PROPERTY_FOCUS_ON_CLICK + }; + sal_Int32 nIdCount = sizeof(nBooleanPropertyAttributeIds) / sizeof(nBooleanPropertyAttributeIds[0]); + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNameCount = sizeof(pBooleanPropertyNames) / sizeof(pBooleanPropertyNames[0]); + OSL_ENSURE((nIdCount == nNameCount), + "OControlExport::exportSpecialAttributes: somebody tampered with the maps (1)!"); + #endif + const sal_Int32* pAttributeId = nBooleanPropertyAttributeIds; + const ::rtl::OUString** pPropertyName = pBooleanPropertyNames; + for ( i = 0; i < nIdCount; ++i, ++pAttributeId, ++pPropertyName ) + { + if ( *pAttributeId& m_nIncludeSpecial) + { + exportBooleanPropertyAttribute( + OAttributeMetaData::getSpecialAttributeNamespace( *pAttributeId ), + OAttributeMetaData::getSpecialAttributeName( *pAttributeId ), + *(*pPropertyName), + ( *pAttributeId == SCA_FOCUS_ON_CLICK ) ? BOOLATTR_DEFAULT_TRUE : BOOLATTR_DEFAULT_FALSE + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~*pAttributeId; + #endif + } + } + } + + // ---------------------- + // the integer properties + { + static sal_Int32 nIntegerPropertyAttributeIds[] = + { // attribute flags + SCA_PAGE_STEP_SIZE + }; + static const ::rtl::OUString* pIntegerPropertyNames[] = + { // property names + &PROPERTY_BLOCK_INCREMENT + }; + static const sal_Int32 nIntegerPropertyAttrDefaults[] = + { // attribute defaults (XML defaults, not runtime defaults!) + 10 + }; + + sal_Int32 nIdCount = sizeof( nIntegerPropertyAttributeIds ) / sizeof( nIntegerPropertyAttributeIds[0] ); + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNameCount = sizeof( pIntegerPropertyNames ) / sizeof( pIntegerPropertyNames[0] ); + OSL_ENSURE( ( nIdCount == nNameCount ), + "OControlExport::exportSpecialAttributes: somebody tampered with the maps (2)!" ); + sal_Int32 nDefaultCount = sizeof( nIntegerPropertyAttrDefaults ) / sizeof( nIntegerPropertyAttrDefaults[0] ); + OSL_ENSURE( ( nIdCount == nDefaultCount ), + "OControlExport::exportSpecialAttributes: somebody tampered with the maps (3)!" ); + #endif + for ( i = 0; i < nIdCount; ++i ) + if ( nIntegerPropertyAttributeIds[i] & m_nIncludeSpecial ) + { + exportInt32PropertyAttribute( + OAttributeMetaData::getSpecialAttributeNamespace( nIntegerPropertyAttributeIds[i] ), + OAttributeMetaData::getSpecialAttributeName( nIntegerPropertyAttributeIds[i] ), + *( pIntegerPropertyNames[i] ), + nIntegerPropertyAttrDefaults[i] + ); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~nIntegerPropertyAttributeIds[i]; + #endif + } + + if ( SCA_STEP_SIZE & m_nIncludeSpecial ) + { + ::rtl::OUString sPropertyName; + if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) ) + sPropertyName = PROPERTY_LINE_INCREMENT; + else if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) ) + sPropertyName = PROPERTY_SPIN_INCREMENT; + else + OSL_ENSURE( sal_False, "OControlExport::exportSpecialAttributes: not property which can be mapped to step-size attribute!" ); + + if ( sPropertyName.getLength() ) + exportInt32PropertyAttribute( + OAttributeMetaData::getSpecialAttributeNamespace( SCA_STEP_SIZE ), + OAttributeMetaData::getSpecialAttributeName( SCA_STEP_SIZE ), + sPropertyName, + 1 + ); + + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~SCA_STEP_SIZE; + #endif + } + + } + + // ------------------- + // the enum properties + { + if (SCA_STATE & m_nIncludeSpecial) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getSpecialAttributeNamespace(SCA_STATE), + OAttributeMetaData::getSpecialAttributeName(SCA_STATE), + PROPERTY_DEFAULT_STATE, + OEnumMapper::getEnumMap(OEnumMapper::epCheckState), + STATE_NOCHECK); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~SCA_STATE; + #endif + } + + if (SCA_CURRENT_STATE & m_nIncludeSpecial) + { + exportEnumPropertyAttribute( + OAttributeMetaData::getSpecialAttributeNamespace(SCA_CURRENT_STATE), + OAttributeMetaData::getSpecialAttributeName(SCA_CURRENT_STATE), + PROPERTY_STATE, + OEnumMapper::getEnumMap(OEnumMapper::epCheckState), + STATE_NOCHECK); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~SCA_CURRENT_STATE; + #endif + } + } + + // -------------------------------------------------------------------- + // some properties which require a special handling + // the repeat delay + { + if ( m_nIncludeSpecial & SCA_REPEAT_DELAY ) + { + DBG_CHECK_PROPERTY( PROPERTY_REPEAT_DELAY, sal_Int32 ); + + sal_Int32 nRepeatDelay = 0; + m_xProps->getPropertyValue( PROPERTY_REPEAT_DELAY ) >>= nRepeatDelay; + Time aTime; + aTime.MakeTimeFromMS( nRepeatDelay ); + + AddAttribute(OAttributeMetaData::getSpecialAttributeNamespace( SCA_REPEAT_DELAY ) + ,OAttributeMetaData::getSpecialAttributeName( SCA_REPEAT_DELAY ) + ,SvXMLUnitConverter::convertTimeDuration( aTime, nRepeatDelay % 1000 ) ); + + exportedProperty( PROPERTY_REPEAT_DELAY ); + + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~SCA_REPEAT_DELAY; + #endif + } + } + + // ---------------------------------- + // the EchoChar property needs special handling, cause it's a Int16, but must be stored as one-character-string + { + if (SCA_ECHO_CHAR & m_nIncludeSpecial) + { + DBG_CHECK_PROPERTY( PROPERTY_ECHO_CHAR, sal_Int16 ); + sal_Int16 nValue(0); + m_xProps->getPropertyValue(PROPERTY_ECHO_CHAR) >>= nValue; + if (nValue) + { + ::rtl::OUString sCharacter(reinterpret_cast<const sal_Unicode*>(&nValue), 1); + AddAttribute( + OAttributeMetaData::getSpecialAttributeNamespace(SCA_ECHO_CHAR), + OAttributeMetaData::getSpecialAttributeName(SCA_ECHO_CHAR), + sCharacter); + } + exportedProperty(PROPERTY_ECHO_CHAR); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~SCA_ECHO_CHAR; + #endif + } + } + + // ---------------------------------- + if ((SCA_MIN_VALUE | SCA_MAX_VALUE) & m_nIncludeSpecial) + { + // need to export the min value and the max value as attributes + // It depends on the real type (FormComponentType) of the control, which properties hold these + // values + const sal_Char* pMinValuePropertyName = NULL; + const sal_Char* pMaxValuePropertyName = NULL; + getValueLimitPropertyNames(m_nClassId, pMinValuePropertyName, pMaxValuePropertyName); + + OSL_ENSURE((NULL == pMinValuePropertyName) == (0 == (SCA_MIN_VALUE & m_nIncludeSpecial)), + "OControlExport::exportCommonControlAttributes: no property found for the min value attribute!"); + OSL_ENSURE((NULL == pMaxValuePropertyName) == (0 == (SCA_MAX_VALUE & m_nIncludeSpecial)), + "OControlExport::exportCommonControlAttributes: no property found for the max value attribute!"); + + // add the two attributes + static const sal_Char* pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MIN_VALUE); + static const sal_Char* pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MAX_VALUE); + static const sal_uInt16 nMinValueNamespaceKey = OAttributeMetaData::getSpecialAttributeNamespace(SCA_MIN_VALUE); + static const sal_uInt16 nMaxValueNamespaceKey = OAttributeMetaData::getSpecialAttributeNamespace(SCA_MAX_VALUE); + + if (pMinValuePropertyName && (SCA_MIN_VALUE & m_nIncludeSpecial)) + exportGenericPropertyAttribute( + nMinValueNamespaceKey, + pMinValueAttributeName, + pMinValuePropertyName); + + if (pMaxValuePropertyName && (SCA_MAX_VALUE & m_nIncludeSpecial)) + exportGenericPropertyAttribute( + nMaxValueNamespaceKey, + pMaxValueAttributeName, + pMaxValuePropertyName); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeSpecial = m_nIncludeSpecial & ~(SCA_MIN_VALUE | SCA_MAX_VALUE); + #endif + } + + // ---------------------------------- + if ( SCA_IMAGE_POSITION & m_nIncludeSpecial ) + { + exportImagePositionAttributes(); + RESET_BIT( m_nIncludeSpecial, SCA_IMAGE_POSITION ); + } + + OSL_ENSURE(0 == m_nIncludeSpecial, + "OControlExport::exportSpecialAttributes: forgot some flags!"); + // in the dbg_util version, we should have removed every bit we handled from the mask, so it should + // be 0 now ... + } + + //--------------------------------------------------------------------- + ::rtl::OUString OControlExport::getScalarListSourceValue() const + { + ::rtl::OUString sListSource; + Any aListSource = m_xProps->getPropertyValue( PROPERTY_LISTSOURCE ); + if ( !( aListSource >>= sListSource ) ) + { + Sequence< ::rtl::OUString > aListSourceSequence; + aListSource >>= aListSourceSequence; + if ( aListSourceSequence.getLength() ) + sListSource = aListSourceSequence[ 0 ]; + } + return sListSource; + } + + //--------------------------------------------------------------------- + void OControlExport::exportListSourceAsAttribute() + { + // DA_LIST_SOURCE needs some special handling + DBG_CHECK_PROPERTY_NO_TYPE( PROPERTY_LISTSOURCE ); + + ::rtl::OUString sListSource = getScalarListSourceValue(); + if ( sListSource.getLength() ) + { // the ListSource property needs to be exported as attribute, and it is not empty + AddAttribute( + OAttributeMetaData::getDatabaseAttributeNamespace(DA_LIST_SOURCE), + OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE), + sListSource); + } + + exportedProperty( PROPERTY_LISTSOURCE ); + } + + //--------------------------------------------------------------------- + void OControlExport::getSequenceInt16PropertyAsSet(const ::rtl::OUString& _rPropertyName, Int16Set& _rOut) + { + Sequence< sal_Int16 > aValueSequence; + DBG_CHECK_PROPERTY(_rPropertyName, Sequence< sal_Int16 >); + m_xProps->getPropertyValue(_rPropertyName) >>= aValueSequence; + + const sal_Int16* pValues = aValueSequence.getConstArray(); + for (sal_Int32 i=0; i<aValueSequence.getLength(); ++i, ++pValues) + _rOut.insert(*pValues); + } + + //--------------------------------------------------------------------- + void OControlExport::exportListSourceAsElements() + { + // the string lists + Sequence< ::rtl::OUString > aItems, aValues; + DBG_CHECK_PROPERTY( PROPERTY_STRING_ITEM_LIST, Sequence< ::rtl::OUString > ); + m_xProps->getPropertyValue(PROPERTY_STRING_ITEM_LIST) >>= aItems; + + DBG_CHECK_PROPERTY( PROPERTY_LISTSOURCE, Sequence< ::rtl::OUString > ); + if ( 0 == ( m_nIncludeDatabase & DA_LIST_SOURCE ) ) + m_xProps->getPropertyValue(PROPERTY_LISTSOURCE) >>= aValues; + // if we exported the list source as attribute, we do not repeat it as sub elements + + // the selection lists + Int16Set aSelection, aDefaultSelection; + getSequenceInt16PropertyAsSet(PROPERTY_SELECT_SEQ, aSelection); + getSequenceInt16PropertyAsSet(PROPERTY_DEFAULT_SELECT_SEQ, aDefaultSelection); + + // the string for "true" + ::rtl::OUString sTrue; + ::rtl::OUStringBuffer sBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertBool(sBuffer, sal_True); + sTrue = sBuffer.makeStringAndClear(); + + // loop through both lists ('til the maximum of both lengths) + const ::rtl::OUString* pItems = aItems.getConstArray(); + const ::rtl::OUString* pValues = aValues.getConstArray(); + + sal_Int32 nItems = aItems.getLength(); + sal_Int32 nValues = aValues.getLength(); + + sal_Int16 nMaxLen = (sal_Int16)std::max(nItems, nValues); + + for (sal_Int16 i=0; i<nMaxLen; ++i ) + { + m_rContext.getGlobalContext().ClearAttrList(); + if (i < nItems) + { + // there is an item at this position + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_LABEL), + OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL), + *pItems); + ++pItems; + } + if (i < nValues) + { + // there is an value at this position + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_VALUE), + OAttributeMetaData::getCommonControlAttributeName(CCA_VALUE), + *pValues); + ++pValues; + } + + Int16SetIterator aSelectedPos = aSelection.find(i); + if (aSelection.end() != aSelectedPos) + { // the item at this position is selected + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_CURRENT_SELECTED), + OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED), + sTrue + ); + aSelection.erase(aSelectedPos); + } + + Int16SetIterator aDefaultSelectedPos = aDefaultSelection.find(i); + if (aDefaultSelection.end() != aDefaultSelectedPos) + { // the item at this position is selected as default + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_SELECTED), + OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED), + sTrue + ); + aDefaultSelection.erase(aDefaultSelectedPos); + } + SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "option", sal_True, sal_True); + } + + // There may be more "selected" or "default-selected" items than there are in the lists in real, + // so we need to store some additional "form:option" items which have no name and no label, but + // one or both of the selected flags. + // 21.05.2001 - 85388 - frank.schoenheit@germany.sun.com + + if ( !aSelection.empty() || !aDefaultSelection.empty() ) + { + sal_Int16 nLastSelected = -1; + if ( !aSelection.empty() ) + nLastSelected = *(--aSelection.end()); + + sal_Int16 nLastDefaultSelected = -1; + if ( !aDefaultSelection.empty() ) + nLastDefaultSelected = *(--aDefaultSelection.end()); + + // the maximum element in both sets + sal_Int16 nLastReferredEntry = std::max(nLastSelected, nLastDefaultSelected); + OSL_ENSURE(nLastReferredEntry >= nMaxLen, "OControlExport::exportListSourceAsElements: inconsistence!"); + // if the maximum (selected or default selected) entry number is less than the maximum item count + // in both lists, the entry number should have been removed from the set + + for (sal_Int16 i=nMaxLen; i<=nLastReferredEntry; ++i) + { + if (aSelection.end() != aSelection.find(i)) + { // the (not existent) item at this position is selected + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_CURRENT_SELECTED), + OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED), + sTrue + ); + } + + if (aDefaultSelection.end() != aDefaultSelection.find(i)) + { // the (not existent) item at this position is selected as default + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_SELECTED), + OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED), + sTrue + ); + } + SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "option", sal_True, sal_True); + } + } + } + + //--------------------------------------------------------------------- + void OControlExport::implStartElement(const sal_Char* _pName) + { + // before we let the base class start it's outer element, we add a wrapper element + const sal_Char *pOuterElementName = getOuterXMLElementName(); + m_pOuterElement = pOuterElementName + ? new SvXMLElementExport( + m_rContext.getGlobalContext(), + XML_NAMESPACE_FORM, + pOuterElementName, sal_True, + sal_True) + : 0; + + // add the attributes for the inner element + exportInnerAttributes(); + + // and start the inner element + OElementExport::implStartElement(_pName); + } + + //--------------------------------------------------------------------- + void OControlExport::implEndElement() + { + // end the inner element + OElementExport::implEndElement(); + + // end the outer element if it exists + delete m_pOuterElement; + m_pOuterElement = NULL; + } + + //--------------------------------------------------------------------- + const sal_Char* OControlExport::getOuterXMLElementName() const + { + return 0; + } + + //--------------------------------------------------------------------- + const sal_Char* OControlExport::getXMLElementName() const + { + return getElementName(m_eType); + } + + //--------------------------------------------------------------------- + void OControlExport::examine() + { + OSL_ENSURE( ( m_nIncludeCommon == 0 ) && ( m_nIncludeSpecial == 0 ) && ( m_nIncludeDatabase == 0 ) + && ( m_nIncludeEvents == 0 ) && ( m_nIncludeBindings == 0), + "OControlExport::examine: called me twice? Not initialized?" ); + + // get the class id to decide which kind of element we need in the XML stream + m_nClassId = FormComponentType::CONTROL; + DBG_CHECK_PROPERTY( PROPERTY_CLASSID, sal_Int16 ); + m_xProps->getPropertyValue(PROPERTY_CLASSID) >>= m_nClassId; + switch (m_nClassId) + { + case FormComponentType::DATEFIELD: + case FormComponentType::TIMEFIELD: + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + case FormComponentType::PATTERNFIELD: + m_eType = FORMATTED_TEXT; + // NO BREAK + case FormComponentType::TEXTFIELD: + { // it's some kind of edit. To know which type we need further investigation + + if (FORMATTED_TEXT != m_eType) + { // not coming from the previous cases which had a class id .ne. TEXTFIELD + + // check if it's a formatted field + if (m_xPropertyInfo->hasPropertyByName(PROPERTY_FORMATKEY)) + { + m_eType = FORMATTED_TEXT; + } + else + { + // all other controls are represented by an ordinary edit control, but which XML control type + // it is depends on the current values of some properties + + // if the EchoChar string is not empty, it is a password field + sal_Int16 nEchoChar = 0; + if (m_xPropertyInfo->hasPropertyByName(PROPERTY_ECHOCHAR)) + // grid columns do not have this property .... + m_xProps->getPropertyValue(PROPERTY_ECHOCHAR) >>= nEchoChar; + if (nEchoChar) + { + m_eType = PASSWORD; + m_nIncludeSpecial |= SCA_ECHO_CHAR; + } + else + { + // if the MultiLine property is sal_True, it is a TextArea + sal_Bool bMultiLine = sal_False; + if (m_xPropertyInfo->hasPropertyByName(PROPERTY_MULTILINE)) + // grid columns do not have this property .... + bMultiLine = ::cppu::any2bool(m_xProps->getPropertyValue(PROPERTY_MULTILINE)); + + if ( bMultiLine ) + m_eType = TEXT_AREA; + else + // the only case left is represented by a Text element + m_eType = TEXT; + } + } + } + + // attributes which are common to all the four types: + // common attributes + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_VALUE | + CCA_PRINTABLE | CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE; + + // database attributes + m_nIncludeDatabase = DA_DATA_FIELD | DA_INPUT_REQUIRED; + + // event attributes + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CHANGE | EA_ON_SELECT; + + // only text and pattern fields have a ConvertEmptyToNull property + if ( ( m_nClassId == FormComponentType::TEXTFIELD ) + || ( m_nClassId == FormComponentType::PATTERNFIELD ) + ) + m_nIncludeDatabase |= DA_CONVERT_EMPTY; + + // all controls but the file control fields have a readonly property + if ( m_nClassId != FormComponentType::FILECONTROL ) + m_nIncludeCommon |= CCA_READONLY; + + // a text field has a max text len + if ( m_nClassId == FormComponentType::TEXTFIELD ) + m_nIncludeCommon |= CCA_MAX_LENGTH; + + // max and min values and validation: + if (FORMATTED_TEXT == m_eType) + { // in general all controls represented as formatted-text have these props + if (FormComponentType::PATTERNFIELD != m_nClassId) + // but the PatternField does not have value limits + m_nIncludeSpecial |= SCA_MAX_VALUE | SCA_MIN_VALUE; + + if (FormComponentType::TEXTFIELD != m_nClassId) + // and the FormattedField does not have a validation flag + m_nIncludeSpecial |= SCA_VALIDATION; + } + + // if it's not a password field or rich text control, the CurrentValue needs to be stored, too + if ( PASSWORD != m_eType ) + m_nIncludeCommon |= CCA_CURRENT_VALUE; + } + break; + + case FormComponentType::FILECONTROL: + m_eType = FILE; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_CURRENT_VALUE | CCA_DISABLED | + CCA_PRINTABLE | CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE | + CCA_VALUE; + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CHANGE | EA_ON_SELECT; + break; + + case FormComponentType::FIXEDTEXT: + m_eType = FIXED_TEXT; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_LABEL | + CCA_PRINTABLE | CCA_TITLE | CCA_FOR; + m_nIncludeSpecial = SCA_MULTI_LINE; + m_nIncludeEvents = EA_CONTROL_EVENTS; + break; + + case FormComponentType::COMBOBOX: + m_eType = COMBOBOX; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_CURRENT_VALUE | + CCA_DISABLED | CCA_DROPDOWN | CCA_MAX_LENGTH | CCA_PRINTABLE | CCA_READONLY | CCA_SIZE | + CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE | CCA_VALUE; + m_nIncludeSpecial = SCA_AUTOMATIC_COMPLETION; + m_nIncludeDatabase = DA_CONVERT_EMPTY | DA_DATA_FIELD | DA_INPUT_REQUIRED | DA_LIST_SOURCE | DA_LIST_SOURCE_TYPE; + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CHANGE | EA_ON_SELECT; + break; + + case FormComponentType::LISTBOX: + m_eType = LISTBOX; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_DROPDOWN | + CCA_PRINTABLE | CCA_SIZE | CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE; + m_nIncludeSpecial = SCA_MULTIPLE; + m_nIncludeDatabase = DA_BOUND_COLUMN | DA_DATA_FIELD | DA_INPUT_REQUIRED | DA_LIST_SOURCE_TYPE; + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CHANGE | EA_ON_CLICK | EA_ON_DBLCLICK; + // check if we need to export the ListSource as attribute + { + // for a list box, if the ListSourceType is VALUE_LIST, no ListSource is stored, but instead + // a sequence of pairs which is build from the StringItemList and the ValueList + ListSourceType eListSourceType = ListSourceType_VALUELIST; + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + m_xProps->getPropertyValue(PROPERTY_LISTSOURCETYPE) >>= eListSourceType; + OSL_ENSURE(bSuccess, "OControlExport::examineControl: could not retrieve the ListSourceType!"); + if (ListSourceType_VALUELIST != eListSourceType) + { + m_nIncludeDatabase |= DA_LIST_SOURCE; + } + } + + break; + + case FormComponentType::COMMANDBUTTON: + m_eType = BUTTON; + m_nIncludeCommon |= CCA_TAB_STOP | CCA_LABEL; + m_nIncludeSpecial = SCA_DEFAULT_BUTTON | SCA_TOGGLE | SCA_FOCUS_ON_CLICK | SCA_IMAGE_POSITION | SCA_REPEAT_DELAY; + // NO BREAK ! + case FormComponentType::IMAGEBUTTON: + if (BUTTON != m_eType) + { + // not coming from the previous case + m_eType = IMAGE; + } + m_nIncludeCommon |= + CCA_NAME | CCA_SERVICE_NAME | CCA_BUTTON_TYPE | CCA_DISABLED | + CCA_IMAGE_DATA | CCA_PRINTABLE | CCA_TAB_INDEX | CCA_TARGET_FRAME | + CCA_TARGET_LOCATION | CCA_TITLE; + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CLICK | EA_ON_DBLCLICK; + break; + + case FormComponentType::CHECKBOX: + m_eType = CHECKBOX; + m_nIncludeSpecial = SCA_CURRENT_STATE | SCA_IS_TRISTATE | SCA_STATE; + // NO BREAK ! + case FormComponentType::RADIOBUTTON: + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_LABEL | CCA_PRINTABLE | + CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE | CCA_VALUE | CCA_VISUAL_EFFECT; + if (CHECKBOX != m_eType) + { // not coming from the previous case + m_eType = RADIO; + m_nIncludeCommon |= CCA_CURRENT_SELECTED | CCA_SELECTED; + } + if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_IMAGE_POSITION ) ) + m_nIncludeSpecial |= SCA_IMAGE_POSITION; + m_nIncludeDatabase = DA_DATA_FIELD | DA_INPUT_REQUIRED; + m_nIncludeEvents = EA_CONTROL_EVENTS | EA_ON_CHANGE; + break; + + case FormComponentType::GROUPBOX: + m_eType = FRAME; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_LABEL | + CCA_PRINTABLE | CCA_TITLE | CCA_FOR; + m_nIncludeEvents = EA_CONTROL_EVENTS; + break; + + case FormComponentType::IMAGECONTROL: + m_eType = IMAGE_FRAME; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_IMAGE_DATA | + CCA_PRINTABLE | CCA_READONLY | CCA_TITLE; + m_nIncludeDatabase = DA_DATA_FIELD | DA_INPUT_REQUIRED; + m_nIncludeEvents = EA_CONTROL_EVENTS; + break; + + case FormComponentType::HIDDENCONTROL: + m_eType = HIDDEN; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_VALUE; + break; + + case FormComponentType::GRIDCONTROL: + m_eType = GRID; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_PRINTABLE | + CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE; + m_nIncludeEvents = EA_CONTROL_EVENTS; + break; + + case FormComponentType::SCROLLBAR: + case FormComponentType::SPINBUTTON: + m_eType = VALUERANGE; + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | CCA_PRINTABLE | + CCA_TITLE | CCA_CURRENT_VALUE | CCA_VALUE | CCA_ORIENTATION; + m_nIncludeSpecial = SCA_MAX_VALUE | SCA_STEP_SIZE | SCA_MIN_VALUE | SCA_REPEAT_DELAY; + + if ( m_nClassId == FormComponentType::SCROLLBAR ) + m_nIncludeSpecial |= SCA_PAGE_STEP_SIZE ; + + m_nIncludeEvents = EA_CONTROL_EVENTS; + break; + + default: + OSL_ENSURE(sal_False, "OControlExport::examineControl: unknown control type (class id)!"); + // NO break! + + case FormComponentType::NAVIGATIONBAR: + // TODO: should we have an own file format for this? + // NO break + + case FormComponentType::CONTROL: + m_eType = GENERIC_CONTROL; + // unknown control type + m_nIncludeCommon = CCA_NAME | CCA_SERVICE_NAME; + // at least a name should be there, 'cause without a name the control could never have been + // inserted into it's parent container + // In addition, the service name is absolutely necessary to create the control upon reading. + m_nIncludeEvents = EA_CONTROL_EVENTS; + // we always should be able to export events - this is not control type dependent + break; + } + + // in general, all control types need to export the control id + m_nIncludeCommon |= CCA_CONTROL_ID; + + // is is a control bound to a calc cell? + if ( FormCellBindingHelper::livesInSpreadsheetDocument( m_xProps ) ) + { + FormCellBindingHelper aHelper( m_xProps, NULL ); + { + if ( aHelper.isCellBinding( aHelper.getCurrentBinding( ) ) ) + { + m_nIncludeBindings |= BA_LINKED_CELL; + if ( m_nClassId == FormComponentType::LISTBOX ) + m_nIncludeBindings |= BA_LIST_LINKING_TYPE; + } + } + + // is it a list-like control which uses a calc cell range as list source? + { + if ( aHelper.isCellRangeListSource( aHelper.getCurrentListSource( ) ) ) + m_nIncludeBindings |= BA_LIST_CELL_RANGE; + } + } + + // is control bound to XForms? + if( getXFormsBindName( m_xProps ).getLength() > 0 ) + { + m_nIncludeBindings |= BA_XFORMS_BIND; + } + + // is (list-)control bound to XForms list? + if( getXFormsListBindName( m_xProps ).getLength() > 0 ) + { + m_nIncludeBindings |= BA_XFORMS_LISTBIND; + } + + // does the control have an XForms submission? + if( getXFormsSubmissionName( m_xProps ).getLength() > 0 ) + { + m_nIncludeBindings |= BA_XFORMS_SUBMISSION; + } + } + + //--------------------------------------------------------------------- + void OControlExport::exportCellBindingAttributes( bool _bIncludeListLinkageType ) + { + try + { + FormCellBindingHelper aHelper( m_xProps, NULL ); + Reference< XValueBinding > xBinding( aHelper.getCurrentBinding() ); + OSL_ENSURE( xBinding.is(), "OControlExport::exportCellBindingAttributes: invalid bindable or invalid binding!" ); + if ( xBinding.is() ) + { + // .................................................... + AddAttribute( + OAttributeMetaData::getBindingAttributeNamespace( BA_LINKED_CELL ), + OAttributeMetaData::getBindingAttributeName( BA_LINKED_CELL ), + aHelper.getStringAddressFromCellBinding( xBinding ) + ); + + // .................................................... + if ( _bIncludeListLinkageType ) + { + sal_Int16 nLinkageType = aHelper.isCellIntegerBinding( xBinding ) ? 1 : 0; + + ::rtl::OUStringBuffer sBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertEnum( + sBuffer, + (sal_uInt16)nLinkageType, + OEnumMapper::getEnumMap( OEnumMapper::epListLinkageType ) + ); + + AddAttribute( + OAttributeMetaData::getBindingAttributeNamespace( BA_LIST_LINKING_TYPE ), + OAttributeMetaData::getBindingAttributeName( BA_LIST_LINKING_TYPE ), + sBuffer.makeStringAndClear() + ); + } + + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlExport::exportCellBindingAttributes: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + void OControlExport::exportXFormsBindAttributes() + { + rtl::OUString sBindName = getXFormsBindName( m_xProps ); + AddAttribute( XML_NAMESPACE_XFORMS, XML_BIND, sBindName ); + } + //--------------------------------------------------------------------- + void OControlExport::exportXFormsListAttributes() + { + rtl::OUString sBindName = getXFormsListBindName( m_xProps ); + AddAttribute( XML_NAMESPACE_FORM, XML_XFORMS_LIST_SOURCE, sBindName ); + } + //--------------------------------------------------------------------- + void OControlExport::exportXFormsSubmissionAttributes() + { + rtl::OUString sSubmission = getXFormsSubmissionName( m_xProps ); + AddAttribute( XML_NAMESPACE_FORM, XML_XFORMS_SUBMISSION, sSubmission ); + } + //--------------------------------------------------------------------- + void OControlExport::exportCellListSourceRange( ) + { + try + { + Reference< XListEntrySink > xSink( m_xProps, UNO_QUERY ); + Reference< XListEntrySource > xSource; + if ( xSink.is() ) + xSource = xSource.query( xSink->getListEntrySource() ); + OSL_ENSURE( xSource.is(), "OControlExport::exportCellListSourceRange: list source or sink!" ); + if ( xSource.is() ) + { + FormCellBindingHelper aHelper( m_xProps, NULL ); + + AddAttribute( + OAttributeMetaData::getBindingAttributeNamespace( BA_LIST_CELL_RANGE ), + OAttributeMetaData::getBindingAttributeName( BA_LIST_CELL_RANGE ), + aHelper.getStringAddressFromCellListSource( xSource ) + ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlExport::exportCellListSourceRange: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + void OControlExport::exportImagePositionAttributes() + { + try + { + sal_Int16 nImagePosition = ImagePosition::Centered; + OSL_VERIFY( m_xProps->getPropertyValue( PROPERTY_IMAGE_POSITION ) >>= nImagePosition ); + OSL_ENSURE( ( nImagePosition >= ImagePosition::LeftTop ) && ( nImagePosition <= ImagePosition::Centered ), + "OControlExport::exportImagePositionAttributes: don't know this image position!" ); + + if ( ( nImagePosition < ImagePosition::LeftTop ) || ( nImagePosition > ImagePosition::Centered ) ) + // this is important to prevent potential buffer overflows below, so don't optimize + nImagePosition = ImagePosition::Centered; + + if ( nImagePosition == ImagePosition::Centered ) + { + AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_POSITION ), GetXMLToken( XML_CENTER ) ); + } + else + { + XMLTokenEnum eXmlImagePositions[] = + { + XML_START, XML_END, XML_TOP, XML_BOTTOM + }; + XMLTokenEnum eXmlImageAligns[] = + { + XML_START, XML_CENTER, XML_END + }; + + XMLTokenEnum eXmlImagePosition = eXmlImagePositions[ nImagePosition / 3 ]; + XMLTokenEnum eXmlImageAlign = eXmlImageAligns [ nImagePosition % 3 ]; + + AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_POSITION ), GetXMLToken( eXmlImagePosition ) ); + AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_ALIGN ), GetXMLToken( eXmlImageAlign ) ); + } + + exportedProperty( PROPERTY_IMAGE_POSITION ); + // some of the controls which have an ImagePosition also have an ImageAlign for compatibility + // reasons. Since the ImageAlign values simply represent a sub set of the ImagePosition values, + // we don't need to export ImageAlign anymore + exportedProperty( PROPERTY_IMAGE_ALIGN ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //--------------------------------------------------------------------- + bool OControlExport::controlHasActiveDataBinding() const + { + try + { + // currently exchanging the data with a database column? + ::rtl::OUString sBoundFieldPropertyName( RTL_CONSTASCII_USTRINGPARAM( "BoundField" ) ); + if ( m_xPropertyInfo.is() && m_xPropertyInfo->hasPropertyByName( sBoundFieldPropertyName ) ) + { + Reference< XPropertySet > xBoundField; + m_xProps->getPropertyValue( sBoundFieldPropertyName ) >>= xBoundField; + if ( xBoundField.is() ) + return true; + } + + // currently exchanging data with an external binding? + Reference< XBindableValue > xBindable( m_xProps, UNO_QUERY ); + if ( xBindable.is() && xBindable->getValueBinding().is() ) + return true; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OColumnExport::controlHasActiveDataBinding: caught an exception!" ); + } + + return false; + } + + //--------------------------------------------------------------------- + bool OControlExport::controlHasUserSuppliedListEntries() const + { + try + { + // an external list source? + Reference< XListEntrySink > xEntrySink( m_xProps, UNO_QUERY ); + if ( xEntrySink.is() && xEntrySink->getListEntrySource().is() ) + return false; + + if ( m_xPropertyInfo.is() && m_xPropertyInfo->hasPropertyByName( PROPERTY_LISTSOURCETYPE ) ) + { + ListSourceType eListSourceType = ListSourceType_VALUELIST; + OSL_VERIFY( m_xProps->getPropertyValue( PROPERTY_LISTSOURCETYPE ) >>= eListSourceType ); + if ( eListSourceType == ListSourceType_VALUELIST ) + // for value lists, the list entries as entered by the user are used + return true; + + // for every other type, the list entries are filled with some data obtained + // from a database - if and only if the ListSource property is not empty + return ( 0 == getScalarListSourceValue().getLength() ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlExport::controlHasUserSuppliedListEntries: caught an exception!" ); + } + + OSL_ENSURE( sal_False, "OControlExport::controlHasUserSuppliedListEntries: unreachable code!" ); + // this method should be called for list and combo boxes only + return true; + } + + //===================================================================== + //= OColumnExport + //===================================================================== + //--------------------------------------------------------------------- + OColumnExport::OColumnExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxControl, const ::rtl::OUString& _rControlId, + const Sequence< ScriptEventDescriptor >& _rEvents) + :OControlExport(_rContext, _rxControl, _rControlId, ::rtl::OUString(), _rEvents) + { + } + + //--------------------------------------------------------------------- + OColumnExport::~OColumnExport() + { + implEndElement(); + } + + //--------------------------------------------------------------------- + void OColumnExport::exportServiceNameAttribute() + { + // the attribute "service name" (which has a slightly different meaning for columns + DBG_CHECK_PROPERTY( PROPERTY_COLUMNSERVICENAME, ::rtl::OUString ); + ::rtl::OUString sColumnServiceName; + m_xProps->getPropertyValue(PROPERTY_COLUMNSERVICENAME) >>= sColumnServiceName; + // the service name is a full qualified one (i.e. com.sun.star.form.TextField), but the + // real service name for the column (for use with the XGridColumnFactory) is only the last + // token of this complete name. + sal_Int32 nLastSep = sColumnServiceName.lastIndexOf('.'); + OSL_ENSURE(-1 != nLastSep, "OColumnExport::startExportElement: invalid service name!"); + sColumnServiceName = sColumnServiceName.copy(nLastSep + 1); + sColumnServiceName = + m_rContext.getGlobalContext().GetNamespaceMap().GetQNameByKey( + XML_NAMESPACE_OOO, sColumnServiceName ); + // add the attribute + AddAttribute( OAttributeMetaData::getCommonControlAttributeNamespace(CCA_SERVICE_NAME) + , OAttributeMetaData::getCommonControlAttributeName(CCA_SERVICE_NAME) + , sColumnServiceName); + // flag the property as "handled" + exportedProperty(PROPERTY_COLUMNSERVICENAME); + + } + + //--------------------------------------------------------------------- + const sal_Char* OColumnExport::getOuterXMLElementName() const + { + return "column"; + } + + //--------------------------------------------------------------------- + void OColumnExport::exportAttributes() + { + OControlExport::exportAttributes(); + + // the attribute "label" + exportStringPropertyAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_LABEL), + OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL), + PROPERTY_LABEL); + + // the style attribute + ::rtl::OUString sStyleName = m_rContext.getObjectStyleName( m_xProps ); + if ( sStyleName.getLength() ) + { + AddAttribute( + OAttributeMetaData::getSpecialAttributeNamespace( SCA_COLUMN_STYLE_NAME ), + OAttributeMetaData::getSpecialAttributeName( SCA_COLUMN_STYLE_NAME ), + sStyleName + ); + } + } + + //--------------------------------------------------------------------- + void OColumnExport::examine() + { + OControlExport::examine(); + + // grid columns miss some properties of the controls they're representing + m_nIncludeCommon &= ~(CCA_FOR | CCA_PRINTABLE | CCA_TAB_INDEX | CCA_TAB_STOP | CCA_LABEL); + m_nIncludeSpecial &= ~(SCA_ECHO_CHAR | SCA_AUTOMATIC_COMPLETION | SCA_MULTIPLE | SCA_MULTI_LINE); + + if (FormComponentType::DATEFIELD != m_nClassId) + // except date fields, no column has the DropDown property + m_nIncludeCommon &= ~CCA_DROPDOWN; + } + + //===================================================================== + //= OFormExport + //===================================================================== + //--------------------------------------------------------------------- + OFormExport::OFormExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxForm, + const Sequence< ScriptEventDescriptor >& _rEvents) + :OElementExport(_rContext, _rxForm, _rEvents) + ,m_bCreateConnectionResourceElement(sal_False) + { + OSL_ENSURE(m_xProps.is(), "OFormExport::OFormExport: invalid arguments!"); + } + + //--------------------------------------------------------------------- + const sal_Char* OFormExport::getXMLElementName() const + { + return "form"; + } + + //--------------------------------------------------------------------- + void OFormExport::exportSubTags() + { + if ( m_bCreateConnectionResourceElement && m_xProps.is() ) + { + m_rContext.getGlobalContext().ClearAttrList(); + ::rtl::OUString sPropValue; + m_xProps->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sPropValue; // if set it is a file url + if ( !sPropValue.getLength() ) + m_xProps->getPropertyValue( PROPERTY_URL ) >>= sPropValue; + if ( sPropValue.getLength() ) + AddAttribute( + OAttributeMetaData::getCommonControlAttributeNamespace(CCA_TARGET_LOCATION), + OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_LOCATION), + sPropValue); + if ( m_rContext.getGlobalContext().GetAttrList().getLength() ) + { + SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, xmloff::token::XML_CONNECTION_RESOURCE, sal_True, sal_True); + } + } + + // let the base class export the remaining properties and the events + OElementExport::exportSubTags(); + // loop through all children + Reference< XIndexAccess > xCollection(m_xProps, UNO_QUERY); + OSL_ENSURE(xCollection.is(), "OFormLayerXMLExport::implExportForm: a form which is not an index access? Suspic�ous!"); + + if (xCollection.is()) + m_rContext.exportCollectionElements(xCollection); + } + + //--------------------------------------------------------------------- + void OFormExport::exportAttributes() + { + sal_Int32 i=0; + + // --------------------- + // the string properties + { + static FormAttributes eStringPropertyIds[] = + { + faName, /*faAction,*/ faCommand, faFilter, faOrder + }; + static ::rtl::OUString aStringPropertyNames[] = + { + PROPERTY_NAME, /*PROPERTY_TARGETURL,*/ PROPERTY_COMMAND, PROPERTY_FILTER, PROPERTY_ORDER + }; + sal_Int32 nIdCount = sizeof(eStringPropertyIds) / sizeof(eStringPropertyIds[0]); + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNameCount = sizeof(aStringPropertyNames) / sizeof(aStringPropertyNames[0]); + OSL_ENSURE((nIdCount == nNameCount), + "OFormExport::exportAttributes: somebody tampered with the maps (1)!"); + #endif + for (i=0; i<nIdCount; ++i) + exportStringPropertyAttribute( + OAttributeMetaData::getFormAttributeNamespace(eStringPropertyIds[i]), + OAttributeMetaData::getFormAttributeName(eStringPropertyIds[i]), + aStringPropertyNames[i]); + // now export the data source name or databaselocation or connection resource + ::rtl::OUString sPropValue; + m_xProps->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sPropValue; + m_bCreateConnectionResourceElement = !sPropValue.getLength(); + if ( !m_bCreateConnectionResourceElement ) + { + INetURLObject aURL(sPropValue); + m_bCreateConnectionResourceElement = ( aURL.GetProtocol() == INET_PROT_FILE ); + if ( !m_bCreateConnectionResourceElement ) + exportStringPropertyAttribute( + OAttributeMetaData::getFormAttributeNamespace(faDatasource), + OAttributeMetaData::getFormAttributeName(faDatasource), + PROPERTY_DATASOURCENAME); + } + else + exportedProperty(PROPERTY_URL); + if ( m_bCreateConnectionResourceElement ) + exportedProperty(PROPERTY_DATASOURCENAME); + } + + // ---------------------- + // the boolean properties + { + static FormAttributes eBooleanPropertyIds[] = + { + faAllowDeletes, faAllowInserts, faAllowUpdates, faApplyFilter, faEscapeProcessing, faIgnoreResult + }; + static const ::rtl::OUString* pBooleanPropertyNames[] = + { + &PROPERTY_ALLOWDELETES, &PROPERTY_ALLOWINSERTS, &PROPERTY_ALLOWUPDATES, &PROPERTY_APPLYFILTER, &PROPERTY_ESCAPEPROCESSING, &PROPERTY_IGNORERESULT + }; + static sal_Int8 nBooleanPropertyAttrFlags[] = + { + BOOLATTR_DEFAULT_TRUE, BOOLATTR_DEFAULT_TRUE, BOOLATTR_DEFAULT_TRUE, BOOLATTR_DEFAULT_FALSE, BOOLATTR_DEFAULT_TRUE, BOOLATTR_DEFAULT_FALSE + }; + sal_Int32 nIdCount = sizeof(eBooleanPropertyIds) / sizeof(eBooleanPropertyIds[0]); + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNameCount = sizeof(pBooleanPropertyNames) / sizeof(pBooleanPropertyNames[0]); + sal_Int32 nFlagsCount = sizeof(nBooleanPropertyAttrFlags) / sizeof(nBooleanPropertyAttrFlags[0]); + OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nFlagsCount), + "OFormExport::exportAttributes: somebody tampered with the maps (2)!"); + #endif + for (i=0; i<nIdCount; ++i) + exportBooleanPropertyAttribute( + OAttributeMetaData::getFormAttributeNamespace(eBooleanPropertyIds[i]), + OAttributeMetaData::getFormAttributeName(eBooleanPropertyIds[i]), + *(pBooleanPropertyNames[i]), + nBooleanPropertyAttrFlags[i] + ); + } + + // ------------------- + // the enum properties + { + static FormAttributes eEnumPropertyIds[] = + { + faEnctype, faMethod, faCommandType, faNavigationMode, faTabbingCycle + }; + static const sal_Char* pEnumPropertyNames[] = + { + PROPERTY_SUBMIT_ENCODING, PROPERTY_SUBMIT_METHOD, PROPERTY_COMMAND_TYPE, PROPERTY_NAVIGATION, PROPERTY_CYCLE + }; + static OEnumMapper::EnumProperties eEnumPropertyMaps[] = + { + OEnumMapper::epSubmitEncoding, OEnumMapper::epSubmitMethod, OEnumMapper::epCommandType, OEnumMapper::epNavigationType, OEnumMapper::epTabCyle + }; + static sal_Int32 nEnumPropertyAttrDefaults[] = + { + FormSubmitEncoding_URL, FormSubmitMethod_GET, CommandType::COMMAND, NavigationBarMode_CURRENT, TabulatorCycle_RECORDS + }; + static sal_Bool nEnumPropertyAttrDefaultFlags[] = + { + sal_False, sal_False, sal_False, sal_False, sal_True + }; + sal_Int32 nIdCount = sizeof(eEnumPropertyIds) / sizeof(eEnumPropertyIds[0]); + #if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNameCount = sizeof(pEnumPropertyNames) / sizeof(pEnumPropertyNames[0]); + sal_Int32 nDefaultCount = sizeof(nEnumPropertyAttrDefaults) / sizeof(nEnumPropertyAttrDefaults[0]); + sal_Int32 nDefaultFlagCount = sizeof(nEnumPropertyAttrDefaultFlags) / sizeof(nEnumPropertyAttrDefaultFlags[0]); + sal_Int32 nMapCount = sizeof(eEnumPropertyMaps) / sizeof(eEnumPropertyMaps[0]); + OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nDefaultCount) && (nDefaultCount == nDefaultFlagCount) && (nDefaultFlagCount == nMapCount), + "OFormExport::exportAttributes: somebody tampered with the maps (3)!"); + #endif + for (i=0; i<nIdCount; ++i) + exportEnumPropertyAttribute( + OAttributeMetaData::getFormAttributeNamespace(eEnumPropertyIds[i]), + OAttributeMetaData::getFormAttributeName(eEnumPropertyIds[i]), + pEnumPropertyNames[i], + OEnumMapper::getEnumMap(eEnumPropertyMaps[i]), + nEnumPropertyAttrDefaults[i], + nEnumPropertyAttrDefaultFlags[i] + ); + } + + // the service name + exportServiceNameAttribute(); + // the target frame + exportTargetFrameAttribute(); + // the target URL + exportTargetLocationAttribute(); + + // master fields + exportStringSequenceAttribute( + OAttributeMetaData::getFormAttributeNamespace(faMasterFields), + OAttributeMetaData::getFormAttributeName(faMasterFields), + PROPERTY_MASTERFIELDS); + // detail fields + exportStringSequenceAttribute( + OAttributeMetaData::getFormAttributeNamespace(faDetailFiels), + OAttributeMetaData::getFormAttributeName(faDetailFiels), + PROPERTY_DETAILFIELDS); + } +//......................................................................... +} // namespace xmloff +//......................................................................... diff --git a/xmloff/source/forms/elementexport.hxx b/xmloff/source/forms/elementexport.hxx new file mode 100644 index 000000000000..d9504271ac04 --- /dev/null +++ b/xmloff/source/forms/elementexport.hxx @@ -0,0 +1,322 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_ELEMENTEXPORT_HXX_ +#define _XMLOFF_ELEMENTEXPORT_HXX_ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include "propertyexport.hxx" +#include "callbacks.hxx" +#include "controlelement.hxx" +#include "valueproperties.hxx" + +class SvXMLElementExport; +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OElementExport + //===================================================================== + class OElementExport : public OPropertyExport + { + protected: + ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor > + m_aEvents; + + SvXMLElementExport* m_pXMLElement; // XML element doing the concrete startElement etc. + + public: + OElementExport(IFormsExportContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxProps, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents); + virtual ~OElementExport(); + + void doExport(); + + protected: + /// get the name of the XML element + virtual const sal_Char* getXMLElementName() const = 0; + /// examine the element we're exporting + virtual void examine(); + /// export the attributes + virtual void exportAttributes(); + /// export any sub tags + virtual void exportSubTags(); + + /** exports the events (as script:events tag) + */ + void exportEvents(); + + /** add the service-name attribute to the export context + */ + virtual void exportServiceNameAttribute(); + + /// start the XML element + virtual void implStartElement(const sal_Char* _pName); + + /// ends the XML element + virtual void implEndElement(); + }; + + //===================================================================== + //= OControlExport + //===================================================================== + /** Helper class for handling xml elements representing a form control + */ + class OControlExport + :public OControlElement + ,public OValuePropertiesMetaData + ,public OElementExport + { + protected: + DECLARE_STL_STDKEY_SET(sal_Int16, Int16Set); + // used below + + ::rtl::OUString m_sControlId; // the control id to use when exporting + ::rtl::OUString m_sReferringControls; // list of referring controls (i.e. their id's) + sal_Int16 m_nClassId; // class id of the control we're representing + ElementType m_eType; // (XML) type of the control we're representing + sal_Int32 m_nIncludeCommon; // common control attributes to include + sal_Int32 m_nIncludeDatabase; // common database attributes to include + sal_Int32 m_nIncludeSpecial; // special attributes to include + sal_Int32 m_nIncludeEvents; // events to include + sal_Int32 m_nIncludeBindings; // binding attributes to include + + SvXMLElementExport* m_pOuterElement; // XML element doing the concrete startElement etc. for the outer element + + public: + /** constructs an object capable of exporting controls + + <p>You need at least two pre-requisites from outside: The control to be exported needs to have a class id + assigned, and you need the list control-ids of all the controls referring to this one as LabelControl.<br/> + This information can't be collected when known only the control itself and not it's complete context.</p> + + @param _rControlId + the control id to use when exporting the control + @param _rReferringControls + the comma-separated list of control-ids of all the controls referring to this one as LabelControl + */ + OControlExport(IFormsExportContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl, + const ::rtl::OUString& _rControlId, + const ::rtl::OUString& _rReferringControls, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rxEvents); + ~OControlExport(); + + protected: + /// start the XML element + virtual void implStartElement(const sal_Char* _pName); + + /// ends the XML element + virtual void implEndElement(); + + /// get the name of the outer XML element + virtual const sal_Char* getOuterXMLElementName() const; + + // get the name of the XML element + virtual const sal_Char* getXMLElementName() const; + + /** examine the control. Some kind of CtorImpl. + */ + virtual void examine(); + + /// exports the attributes for the outer element + void exportOuterAttributes(); + + /// exports the attributes for the inner element + void exportInnerAttributes(); + + /// export the attributes + virtual void exportAttributes(); + + /** writes everything which needs to be represented as sub tag + */ + void exportSubTags() throw (::com::sun::star::uno::Exception); + + /** adds common control attributes to the XMLExport context given + + <p>The attribute list of the context is not cleared initially, this is the responsibility of the caller.</p> + */ + void exportCommonControlAttributes(); + + /** adds database attributes to the XMLExport context given + + <p>The attribute list of the context is not cleared initially, this is the responsibility of the caller.</p> + */ + void exportDatabaseAttributes(); + + /** adds the XML attributes which are related to binding controls to + external values and/or list sources + */ + void exportBindingAtributes(); + + /** adds attributes which are special to a control type to the export context's attribute list + */ + void exportSpecialAttributes(); + + /** exports the ListSource property of a control as attribute + + The ListSource property may be exported in different ways: For a ComboBox, it is an attribute + of the form:combobox element. + + For a ListBox, it's an attribute if the ListSourceType states that the ListBox does <em>not</em> + display a value list. In case of a value list, the ListSource is not exported, and the pairs of + StringItem/ValueItem are exported as sub-elements. + + This method does the attribute part: It exports the ListSource property as attribute, not caring + about whether the object is a ComboBox or a ListBox. + */ + void exportListSourceAsAttribute(); + + /** exports the ListSource property of a control as XML elements + + @see exportListSourceAsAttribute + */ + void exportListSourceAsElements(); + + /** get's a Sequence< sal_Int16 > property value as set of sal_Int16's + @param _rPropertyName + the property name to use + @param _rOut + out parameter. The set of integers. + */ + void getSequenceInt16PropertyAsSet(const ::rtl::OUString& _rPropertyName, Int16Set& _rOut); + + /** exports the attribute which descrives a cell value binding of a control + in a spreadsheet document + */ + void exportCellBindingAttributes( bool _bIncludeListLinkageType ); + + /** exports the attribute(s) which bind this control to XForms */ + void exportXFormsBindAttributes(); + + /** exports the attribute(s) which bind the list of a list + control to XForms */ + void exportXFormsListAttributes(); + + /** exports the attribute(s) for an XForms submission */ + void exportXFormsSubmissionAttributes(); + + /** exports the attribute which descrives a cell range which acts as list source for + a list-like control + */ + void exportCellListSourceRange( ); + + /** exports the attribut(s) for the ImagePosition property + */ + void exportImagePositionAttributes(); + + /** determines whether the control we're exporting has an active data binding. + + Bindings which count here are: + <ul><li>an established connection to a database field</li> + <li>a binding to an external value supplier (<type scope="com::sun::star::form::binding">XValueBinding</type>)</li> + </ul> + */ + bool controlHasActiveDataBinding() const; + + /** retrieves the string specifying the ListSource of a list or combo box + */ + ::rtl::OUString getScalarListSourceValue() const; + + /** determines whether the list entries (of a combo or list box) are supplied by the user + + List entries may be + <ul><li>specified by the user</li> + <li>specified by an external list source (<type scope="com::sun::star::form::binding">XListEntrySource</type>)</li> + <li>obtained from a database query (in various ways)</li> + </ul> + + In the latter two cases, this method will return <FALSE/> + */ + bool controlHasUserSuppliedListEntries() const; + }; + + //===================================================================== + //= OColumnExport + //===================================================================== + /** Helper class for exporting a grid column + */ + class OColumnExport : public OControlExport + { + public: + /** ctor + @see OColumnExport::OColumnExport + */ + OColumnExport(IFormsExportContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl, + const ::rtl::OUString& _rControlId, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rxEvents); + + ~OColumnExport(); + + protected: + // OControlExport overridables + virtual const sal_Char* getOuterXMLElementName() const; + virtual void exportServiceNameAttribute(); + virtual void exportAttributes(); + + // OElementExport overridables + virtual void examine(); + }; + + //===================================================================== + //= OFormExport + //===================================================================== + /** Helper class for handling xml elements representing a form + + <p>In opposite to the class <type>OControlExport</type>, OFormExport is unable to export a <em>complete</em> + form. Instead the client has to care for sub elements of the form itself.</p> + */ + class OFormExport + :public OControlElement + ,public OElementExport + { + sal_Bool m_bCreateConnectionResourceElement; + public: + /** constructs an object capable of exporting controls + */ + OFormExport(IFormsExportContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxForm, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rxEvents + ); + + protected: + virtual const sal_Char* getXMLElementName() const; + virtual void exportSubTags(); + virtual void exportAttributes(); + }; +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_ELEMENTEXPORT_HXX_ + diff --git a/xmloff/source/forms/elementimport.cxx b/xmloff/source/forms/elementimport.cxx new file mode 100644 index 000000000000..a39576bd2184 --- /dev/null +++ b/xmloff/source/forms/elementimport.cxx @@ -0,0 +1,2029 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include <algorithm> +#include "elementimport.hxx" +#include <xmloff/xmlimp.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmluconv.hxx> +#include "strings.hxx" +#include "callbacks.hxx" +#include "attriblistmerge.hxx" +#include "xmlnmspe.hxx" +#include "eventimport.hxx" +#include <xmloff/txtstyli.hxx> +#include "formenums.hxx" +#include <xmloff/xmltoken.hxx> +#include "gridcolumnproptranslator.hxx" +#include <comphelper/extract.hxx> +#include <comphelper/types.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/awt/ImagePosition.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +/** === end UNO includes === **/ +#include <tools/urlobj.hxx> +#include <tools/time.hxx> +#include <rtl/logfile.hxx> + +#include <algorithm> +#include <functional> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::xmloff::token; + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::script; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::xml; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::text; + using namespace ::comphelper; + +#define PROPID_VALUE 1 +#define PROPID_CURRENT_VALUE 2 +#define PROPID_MIN_VALUE 3 +#define PROPID_MAX_VALUE 4 + + //===================================================================== + struct PropertyValueLess + { + sal_Bool operator()(const PropertyValue& _rLeft, const PropertyValue& _rRight) + { + return _rLeft.Name < _rRight.Name; + } + }; + + //===================================================================== + struct PropertyValueCompare : public ::std::binary_function< PropertyValue, ::rtl::OUString, bool> + { + bool operator() (const PropertyValue& lhs, const ::rtl::OUString& rhs) const + { + return lhs.Name == rhs; + } + bool operator() (const ::rtl::OUString& lhs, const PropertyValue& rhs) const + { + return lhs == rhs.Name; + } + }; + + //===================================================================== + template <class ELEMENT> + void pushBackSequenceElement(Sequence< ELEMENT >& _rContainer, const ELEMENT& _rElement) + { + sal_Int32 nLen = _rContainer.getLength(); + _rContainer.realloc(nLen + 1); + _rContainer[nLen] = _rElement; + } + + //===================================================================== + //= OElementNameMap + //===================================================================== + //--------------------------------------------------------------------- + OElementNameMap::MapString2Element OElementNameMap::s_sElementTranslations; + + //--------------------------------------------------------------------- + const OControlElement::ElementType& operator ++(OControlElement::ElementType& _e) + { + OControlElement::ElementType e = _e; + sal_Int32 nAsInt = static_cast<sal_Int32>(e); + _e = static_cast<OControlElement::ElementType>( ++nAsInt ); + return _e; + } + + //--------------------------------------------------------------------- + OControlElement::ElementType OElementNameMap::getElementType(const ::rtl::OUString& _rName) + { + if ( s_sElementTranslations.empty() ) + { // initialize + for (ElementType eType=(ElementType)0; eType<UNKNOWN; ++eType) + s_sElementTranslations[::rtl::OUString::createFromAscii(getElementName(eType))] = eType; + } + ConstMapString2ElementIterator aPos = s_sElementTranslations.find(_rName); + if (s_sElementTranslations.end() != aPos) + return aPos->second; + + return UNKNOWN; + } + + //===================================================================== + //= OElementImport + //===================================================================== + //--------------------------------------------------------------------- + OElementImport::OElementImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer) + :OPropertyImport(_rImport, _nPrefix, _rName) + ,m_rFormImport(_rImport) + ,m_rEventManager(_rEventManager) + ,m_pStyleElement( NULL ) + ,m_xParentContainer(_rxParentContainer) + { + OSL_ENSURE(m_xParentContainer.is(), "OElementImport::OElementImport: invalid parent container!"); + } + + //--------------------------------------------------------------------- + OElementImport::~OElementImport() + { + } + + //--------------------------------------------------------------------- + void OElementImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + ENTER_LOG_CONTEXT( "xmloff::OElementImport - importing one element" ); + // call the base class. This should give us enough information (especially the service name) + // to create our UNO element + OPropertyImport::StartElement(_rxAttrList); + + // create the element + m_xElement = createElement(); + if ( !m_xInfo.is() && m_xElement.is() ) + m_xInfo = m_xElement->getPropertySetInfo(); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OElementImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList) + { + if( token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) && (XML_NAMESPACE_OFFICE == _nPrefix)) + return new OFormEventsImportContext(m_rFormImport.getGlobalContext(), _nPrefix, _rLocalName, *this); + + return OPropertyImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); + } + + //--------------------------------------------------------------------- + void OElementImport::EndElement() + { + OSL_ENSURE(m_xElement.is(), "OElementImport::EndElement: invalid element created!"); + if (!m_xElement.is()) + return; + + // set all the properties we collected +#if OSL_DEBUG_LEVEL > 0 + // check if the object has all the properties + // (We do this in the non-pro version only. Doing it all the time would be much to expensive) + if ( m_xInfo.is() ) + { + PropertyValueArray::iterator aEnd = m_aValues.end(); + for ( PropertyValueArray::iterator aCheck = m_aValues.begin(); + aCheck != aEnd; + ++aCheck + ) + { + OSL_ENSURE(m_xInfo->hasPropertyByName(aCheck->Name), + ::rtl::OString("OElementImport::EndElement: read a property (") + += ::rtl::OString(aCheck->Name.getStr(), aCheck->Name.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString(") which does not exist on the element!")); + } + } +#endif + OSL_ENSURE(!m_aValues.empty(), "OElementImport::EndElement: no properties read!"); + + // set the properties + const Reference< XMultiPropertySet > xMultiProps(m_xElement, UNO_QUERY); + sal_Bool bSuccess = sal_False; + if (xMultiProps.is()) + { + // translate our properties so that the XMultiPropertySet can handle them + + // sort our property value array so that we can use it in a setPropertyValues + ::std::sort( m_aValues.begin(), m_aValues.end(), PropertyValueLess()); + + // the names + Sequence< ::rtl::OUString > aNames(m_aValues.size()); + ::rtl::OUString* pNames = aNames.getArray(); + // the values + Sequence< Any > aValues(m_aValues.size()); + Any* pValues = aValues.getArray(); + // copy + + PropertyValueArray::iterator aEnd = m_aValues.end(); + for ( PropertyValueArray::iterator aPropValues = m_aValues.begin(); + aPropValues != aEnd; + ++aPropValues, ++pNames, ++pValues + ) + { + *pNames = aPropValues->Name; + *pValues = aPropValues->Value; + } + + try + { + xMultiProps->setPropertyValues(aNames, aValues); + bSuccess = sal_True; + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OElementImport::EndElement: could not set the properties (using the XMultiPropertySet)!"); + } + } + + if (!bSuccess) + { // no XMultiPropertySet or setting all properties at once failed + PropertyValueArray::iterator aEnd = m_aValues.end(); + for ( PropertyValueArray::iterator aPropValues = m_aValues.begin(); + aPropValues != aEnd; + ++aPropValues + ) + { + // this try/catch here is expensive, but because this is just a fallback which should normally not be + // used it's acceptable this way ... + try + { + m_xElement->setPropertyValue(aPropValues->Name, aPropValues->Value); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, + ::rtl::OString("OElementImport::EndElement: could not set the property \"") + += ::rtl::OString(aPropValues->Name.getStr(), aPropValues->Name.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\"!")); + } + } + } + + // set the generic properties + implImportGenericProperties(); + + // set the style properties + if ( m_pStyleElement && m_xElement.is() ) + { + Reference< XPropertySet > xPropTranslation = + new OGridColumnPropertyTranslator( Reference< XMultiPropertySet >( m_xElement, UNO_QUERY ) ); + const_cast< XMLTextStyleContext* >( m_pStyleElement )->FillPropertySet( xPropTranslation ); + + const ::rtl::OUString sNumberStyleName = const_cast< XMLTextStyleContext* >( m_pStyleElement )->GetDataStyleName( ); + if ( sNumberStyleName.getLength() ) + // the style also has a number (sub) style + m_rContext.applyControlNumberStyle( m_xElement, sNumberStyleName ); + } + + // insert the element into the parent container + if (!m_sName.getLength()) + { + OSL_ENSURE(sal_False, "OElementImport::EndElement: did not find a name attribute!"); + m_sName = implGetDefaultName(); + } + + m_xParentContainer->insertByName(m_sName, makeAny(m_xElement)); + LEAVE_LOG_CONTEXT( ); + } + + //--------------------------------------------------------------------- + void OElementImport::implImportGenericProperties() + { + if ( m_aGenericValues.empty() ) + return; + + Reference< XPropertyContainer > xDynamicProperties( m_xElement, UNO_QUERY ); + + PropertyValueArray::iterator aEnd = m_aGenericValues.end(); + for ( PropertyValueArray::iterator aPropValues = + m_aGenericValues.begin(); + aPropValues != aEnd; + ++aPropValues + ) + { + // check property type for numeric types before setting + // the property + try + { + // if such a property does not yet exist at the element, create it if necessary + const bool bExistentProperty = m_xInfo->hasPropertyByName( aPropValues->Name ); + if ( !bExistentProperty ) + { + if ( !xDynamicProperties.is() ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OString aMessage( "OElementImport::implImportGenericProperties: encountered an unknown property (" ); + aMessage += ::rtl::OUStringToOString( aPropValues->Name, RTL_TEXTENCODING_ASCII_US ); + aMessage += "), but component is no PropertyBag!"; + OSL_ENSURE( false, aMessage.getStr() ); + #endif + continue; + } + + xDynamicProperties->addProperty( + aPropValues->Name, + PropertyAttribute::BOUND | PropertyAttribute::REMOVEABLE, + aPropValues->Value + ); + + // re-fetch the PropertySetInfo + m_xInfo = m_xElement->getPropertySetInfo(); + } + + // determine the type of the value (source forthe following conversion) + TypeClass eValueTypeClass = aPropValues->Value.getValueTypeClass(); + const sal_Bool bValueIsSequence = TypeClass_SEQUENCE == eValueTypeClass; + if ( bValueIsSequence ) + { + uno::Type aSimpleType( getSequenceElementType( aPropValues->Value.getValueType() ) ); + eValueTypeClass = aSimpleType.getTypeClass(); + } + + // determine the type of the property (target forthe following conversion) + const Property aProperty( m_xInfo->getPropertyByName( aPropValues->Name ) ); + TypeClass ePropTypeClass = aProperty.Type.getTypeClass(); + const sal_Bool bPropIsSequence = TypeClass_SEQUENCE == ePropTypeClass; + if( bPropIsSequence ) + { + uno::Type aSimpleType( ::comphelper::getSequenceElementType( aProperty.Type ) ); + ePropTypeClass = aSimpleType.getTypeClass(); + } + + if ( bPropIsSequence != bValueIsSequence ) + { + OSL_ENSURE( false, "OElementImport::implImportGenericProperties: either both value and property should be a sequence, or none of them!" ); + continue; + } + + if ( bValueIsSequence ) + { + OSL_ENSURE( eValueTypeClass == TypeClass_ANY, + "OElementImport::implImportGenericProperties: only ANYs should have been imported as generic list property!" ); + // (OPropertyImport should produce only Sequencer< Any >, since it cannot know the real type + + OSL_ENSURE( ePropTypeClass == TypeClass_SHORT, + "OElementImport::implImportGenericProperties: conversion to sequences other than 'sequence< short >' not implemented, yet!" ); + + Sequence< Any > aXMLValueList; + aPropValues->Value >>= aXMLValueList; + Sequence< sal_Int16 > aPropertyValueList( aXMLValueList.getLength() ); + + const Any* pXMLValue = aXMLValueList.getConstArray(); + sal_Int16* pPropValue = aPropertyValueList.getArray(); + + for ( sal_Int32 i=0; i<aXMLValueList.getLength(); ++i, ++pXMLValue, ++pPropValue ) + { + // only value sequences of numeric types implemented so far. + double nVal( 0 ); + OSL_VERIFY( *pXMLValue >>= nVal ); + *pPropValue = static_cast< sal_Int16 >( nVal ); + } + + aPropValues->Value <<= aPropertyValueList; + } + else if ( ePropTypeClass != eValueTypeClass ) + { + switch ( eValueTypeClass ) + { + case TypeClass_DOUBLE: + { + double nVal = 0; + aPropValues->Value >>= nVal; + switch( ePropTypeClass ) + { + case TypeClass_BYTE: + aPropValues->Value <<= static_cast< sal_Int8 >( nVal ); + break; + case TypeClass_SHORT: + aPropValues->Value <<= static_cast< sal_Int16 >( nVal ); + break; + case TypeClass_LONG: + case TypeClass_ENUM: + aPropValues->Value <<= static_cast< sal_Int32 >( nVal ); + break; + case TypeClass_HYPER: + aPropValues->Value <<= static_cast< sal_Int64 >( nVal ); + break; + default: + OSL_ENSURE( false, "OElementImport::implImportGenericProperties: unsupported value type!" ); + break; + } + } + break; + default: + OSL_ENSURE( false, "OElementImport::implImportGenericProperties: non-double values not supported!" ); + break; + } + } + + m_xElement->setPropertyValue( aPropValues->Name, aPropValues->Value ); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, + ::rtl::OString("OElementImport::EndElement: could not set the property \"") + += ::rtl::OString(aPropValues->Name.getStr(), aPropValues->Name.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\"!")); + } + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString OElementImport::implGetDefaultName() const + { + // no optimization here. If this method gets called, the XML stream did not contain a name for the + // element, which is a heavy error. So in this case we don't care for performance + Sequence< ::rtl::OUString > aNames = m_xParentContainer->getElementNames(); + static const ::rtl::OUString sUnnamedName = ::rtl::OUString::createFromAscii("unnamed"); + + ::rtl::OUString sReturn; + const ::rtl::OUString* pNames = NULL; + const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength(); + for (sal_Int32 i=0; i<32768; ++i) // the limit is nearly arbitrary ... + { + // assemble the new name (suggestion) + sReturn = sUnnamedName; + sReturn += ::rtl::OUString::valueOf(i); + // check the existence (this is the bad performance part ....) + for (pNames = aNames.getConstArray(); pNames<pNamesEnd; ++pNames) + { + if (*pNames == sReturn) + { + break; + } + } + if (pNames<pNamesEnd) + // found the name + continue; + return sReturn; + } + OSL_ENSURE(sal_False, "OElementImport::implGetDefaultName: did not find a free name!"); + return sUnnamedName; + } + + //--------------------------------------------------------------------- + void OElementImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + if (!m_sServiceName.getLength() && + token::IsXMLToken( _rLocalName, token::XML_CONTROL_IMPLEMENTATION)) + { // it's the service name + + ::rtl::OUString sImplName; + const sal_uInt16 nImplPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( _rValue, + &sImplName ); + m_sServiceName = XML_NAMESPACE_OOO==nImplPrefix ? sImplName + :_rValue; + } + else + { + if (!m_sName.getLength() && + token::IsXMLToken( _rLocalName, token::XML_NAME)) + // remember the name for later use in EndElement + m_sName = _rValue; + + // maybe it's the style attribute? + if ( token::IsXMLToken( _rLocalName, token::XML_TEXT_STYLE_NAME ) ) + { + const SvXMLStyleContext* pStyleContext = m_rContext.getStyleElement( _rValue ); + OSL_ENSURE( pStyleContext, "OPropertyImport::handleAttribute: do not know the style!" ); + // remember the element for later usage. + m_pStyleElement = PTR_CAST( XMLTextStyleContext, pStyleContext ); + } + else + // let the base class handle it + OPropertyImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + } + + //--------------------------------------------------------------------- + Reference< XPropertySet > OElementImport::createElement() + { + Reference< XPropertySet > xReturn; + if (m_sServiceName.getLength()) + { + Reference< XInterface > xPure = m_rFormImport.getGlobalContext().getServiceFactory()->createInstance(m_sServiceName); + OSL_ENSURE(xPure.is(), + ::rtl::OString("OElementImport::createElement: service factory gave me no object (service name: ") + += ::rtl::OString(m_sServiceName.getStr(), m_sServiceName.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString(")!")); + xReturn = Reference< XPropertySet >(xPure, UNO_QUERY); + } + else + OSL_ENSURE(sal_False, "OElementImport::createElement: no service name to create an element!"); + + return xReturn; + } + + //--------------------------------------------------------------------- + void OElementImport::registerEvents(const Sequence< ScriptEventDescriptor >& _rEvents) + { + OSL_ENSURE(m_xElement.is(), "OElementImport::registerEvents: no element to register events for!"); + m_rEventManager.registerEvents(m_xElement, _rEvents); + } + + //--------------------------------------------------------------------- + void OElementImport::simulateDefaultedAttribute(const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, const sal_Char* _pAttributeDefault) + { + OSL_ENSURE( m_xInfo.is(), "OPropertyImport::simulateDefaultedAttribute: the component should be more gossipy about it's properties!" ); + + if ( !m_xInfo.is() || m_xInfo->hasPropertyByName( _rPropertyName ) ) + { + ::rtl::OUString sLocalAttrName = ::rtl::OUString::createFromAscii(_pAttributeName); + if ( !encounteredAttribute( sLocalAttrName ) ) + handleAttribute( XML_NAMESPACE_FORM, sLocalAttrName, ::rtl::OUString::createFromAscii( _pAttributeDefault ) ); + } + } + + //===================================================================== + //= OControlImport + //===================================================================== + //--------------------------------------------------------------------- + OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer) + :OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) + ,m_eElementType(OControlElement::UNKNOWN) + { + } + + //--------------------------------------------------------------------- + OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) + :OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) + ,m_eElementType(_eType) + { + } + + //--------------------------------------------------------------------- + void OControlImport::addOuterAttributes(const Reference< sax::XAttributeList >& _rxOuterAttribs) + { + OSL_ENSURE(!m_xOuterAttributes.is(), "OControlImport::addOuterAttributes: already have these attributes!"); + m_xOuterAttributes = _rxOuterAttribs; + } + + //--------------------------------------------------------------------- + void OControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + static const sal_Char* pControlIdAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CONTROL_ID); + static const sal_Char* pLinkedCellAttributeName = OAttributeMetaData::getBindingAttributeName(BA_LINKED_CELL); + + if ( !m_sControlId.getLength() && _rLocalName.equalsAscii( pControlIdAttributeName ) ) + { // it's the control id + m_sControlId = _rValue; + } + else if ( _rLocalName.equalsAscii( pLinkedCellAttributeName ) ) + { // it's the address of a spreadsheet cell + m_sBoundCellAddress = _rValue; + } + else if ( _nNamespaceKey == XML_NAMESPACE_XFORMS && IsXMLToken( _rLocalName, XML_BIND ) ) + { + m_sBindingID = _rValue; + } + else if ( _nNamespaceKey == XML_NAMESPACE_FORM && IsXMLToken( _rLocalName, XML_XFORMS_LIST_SOURCE ) ) + { + m_sListBindingID = _rValue; + } + else if ( (_nNamespaceKey == XML_NAMESPACE_FORM && IsXMLToken( _rLocalName, XML_XFORMS_SUBMISSION ) ) || + ( _nNamespaceKey == XML_NAMESPACE_XFORMS && IsXMLToken( _rLocalName, XML_SUBMISSION ) ) ) + { + m_sSubmissionID = _rValue; + } + else + { + static const sal_Char* pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_VALUE); + static const sal_Char* pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_VALUE); + static const sal_Char* pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MIN_VALUE); + static const sal_Char* pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MAX_VALUE); + static const sal_Char* pRepeatDelayAttributeName = OAttributeMetaData::getSpecialAttributeName( SCA_REPEAT_DELAY ); + + sal_Int32 nHandle = -1; + if ( _rLocalName.equalsAscii( pValueAttributeName ) ) + nHandle = PROPID_VALUE; + else if ( _rLocalName.equalsAscii( pCurrentValueAttributeName ) ) + nHandle = PROPID_CURRENT_VALUE; + else if ( _rLocalName.equalsAscii( pMinValueAttributeName ) ) + nHandle = PROPID_MIN_VALUE; + else if ( _rLocalName.equalsAscii( pMaxValueAttributeName ) ) + nHandle = PROPID_MAX_VALUE; + if ( nHandle != -1 ) + { + // for the moment, simply remember the name and the value + PropertyValue aProp; + aProp.Name = _rLocalName; + aProp.Handle = nHandle; + aProp.Value <<= _rValue; + m_aValueProperties.push_back(aProp); + } + else if ( _rLocalName.equalsAscii( pRepeatDelayAttributeName ) ) + { + ::Time aTime; + sal_Int32 nFractions = 0; + if ( SvXMLUnitConverter::convertTimeDuration( _rValue, aTime, &nFractions ) ) + { + PropertyValue aProp; + aProp.Name = PROPERTY_REPEAT_DELAY; + aProp.Value <<= (sal_Int32)( ( ( aTime.GetMSFromTime() / 1000 ) * 1000 ) + nFractions ); + + implPushBackPropertyValue(aProp); + } + } + else + OElementImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + } + + //--------------------------------------------------------------------- + void OControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > xAttributes; + if( m_xOuterAttributes.is() ) + { + // merge the attribute lists + OAttribListMerger* pMerger = new OAttribListMerger; + // our own one + pMerger->addList(_rxAttrList); + // and the ones of our enclosing element + pMerger->addList(m_xOuterAttributes); + xAttributes = pMerger; + } + else + { + xAttributes = _rxAttrList; + } + + // let the base class handle all the attributes + OElementImport::StartElement(xAttributes); + + if ( !m_aValueProperties.empty() && m_xElement.is()) + { + // get the property set info + if (!m_xInfo.is()) + { + OSL_ENSURE(sal_False, "OControlImport::StartElement: no PropertySetInfo!"); + return; + } + + const sal_Char* pValueProperty = NULL; + const sal_Char* pCurrentValueProperty = NULL; + const sal_Char* pMinValueProperty = NULL; + const sal_Char* pMaxValueProperty = NULL; + + sal_Bool bRetrievedValues = sal_False; + sal_Bool bRetrievedValueLimits = sal_False; + + // get the class id of our element + sal_Int16 nClassId = FormComponentType::CONTROL; + m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; + + // translate the value properties we collected in handleAttributes + PropertyValueArray::iterator aEnd = m_aValueProperties.end(); + for ( PropertyValueArray::iterator aValueProps = m_aValueProperties.begin(); + aValueProps != aEnd; + ++aValueProps + ) + { + switch (aValueProps->Handle) + { + case PROPID_VALUE: + case PROPID_CURRENT_VALUE: + { + // get the property names + if (!bRetrievedValues) + { + getValuePropertyNames(m_eElementType, nClassId, pCurrentValueProperty, pValueProperty); + bRetrievedValues = sal_True; + } + OSL_ENSURE((PROPID_VALUE != aValueProps->Handle) || pValueProperty, + "OControlImport::StartElement: the control does not have a value property!"); + OSL_ENSURE((PROPID_CURRENT_VALUE != aValueProps->Handle) || pCurrentValueProperty, + "OControlImport::StartElement: the control does not have a current-value property!"); + + // transfer the name + if (PROPID_VALUE == aValueProps->Handle) + aValueProps->Name = ::rtl::OUString::createFromAscii(pValueProperty); + else + aValueProps->Name = ::rtl::OUString::createFromAscii(pCurrentValueProperty); + } + break; + case PROPID_MIN_VALUE: + case PROPID_MAX_VALUE: + { + // get the property names + if (!bRetrievedValueLimits) + { + getValueLimitPropertyNames(nClassId, pMinValueProperty, pMaxValueProperty); + bRetrievedValueLimits = sal_True; + } + OSL_ENSURE((PROPID_MIN_VALUE != aValueProps->Handle) || pMinValueProperty, + "OControlImport::StartElement: the control does not have a value property!"); + OSL_ENSURE((PROPID_MAX_VALUE != aValueProps->Handle) || pMaxValueProperty, + "OControlImport::StartElement: the control does not have a current-value property!"); + + // transfer the name + if (PROPID_MIN_VALUE == aValueProps->Handle) + aValueProps->Name = ::rtl::OUString::createFromAscii(pMinValueProperty); + else + aValueProps->Name = ::rtl::OUString::createFromAscii(pMaxValueProperty); + } + break; + } + + // translate the value + implTranslateValueProperty(m_xInfo, *aValueProps); + // add the property to the base class' array + implPushBackPropertyValue(*aValueProps); + } + } + } + + //--------------------------------------------------------------------- + void OControlImport::implTranslateValueProperty(const Reference< XPropertySetInfo >& _rxPropInfo, + PropertyValue& _rPropValue) + { + OSL_ENSURE(_rxPropInfo->hasPropertyByName(_rPropValue.Name), + "OControlImport::implTranslateValueProperty: invalid property name!"); + + // retrieve the type of the property + Property aProp = _rxPropInfo->getPropertyByName(_rPropValue.Name); + // the untranslated string value as read in handleAttribute + ::rtl::OUString sValue; + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rPropValue.Value >>= sValue; + OSL_ENSURE(bSuccess, "OControlImport::implTranslateValueProperty: supposed to be called with non-translated string values!"); + + if (TypeClass_ANY == aProp.Type.getTypeClass()) + { + // we have exactly 2 properties where this type class is allowed: + OSL_ENSURE( + (0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_VALUE)) + || (0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_DEFAULT)), + "OControlImport::implTranslateValueProperty: invalid property type/name combination!"); + + // Both properties are allowed to have a double or a string value, + // so first try to convert the string into a number + double nValue; + if (GetImport().GetMM100UnitConverter().convertDouble(nValue, sValue)) + _rPropValue.Value <<= nValue; + else + _rPropValue.Value <<= sValue; + } + else + _rPropValue.Value = PropertyConversion::convertString(GetImport(), aProp.Type, sValue); + } + + //--------------------------------------------------------------------- + void OControlImport::EndElement() + { + OSL_ENSURE(m_xElement.is(), "OControlImport::EndElement: invalid control!"); + if ( !m_xElement.is() ) + return; + + // register our control with it's id + if (m_sControlId.getLength()) + m_rFormImport.registerControlId(m_xElement, m_sControlId); + // it's allowed to have no control id. In this case we're importing a column + + // one more pre-work to do: + // when we set default values, then by definition the respective value is set + // to this default value, too. This means if the sequence contains for example + // a DefaultText value, then the Text will be affected by this, too. + // In case the Text is not part of the property sequence (or occurs _before_ + // the DefaultText, which can happen for other value/default-value property names), + // this means that the Text (the value property) is incorrectly imported. + // #102475# - 04.09.2002 - fs@openoffice.org + + sal_Bool bRestoreValuePropertyValue = sal_False; + Any aValuePropertyValue; + + sal_Int16 nClassId = FormComponentType::CONTROL; + try + { + // get the class id of our element + m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the class id!" ); + } + + const sal_Char* pValueProperty = NULL; + const sal_Char* pDefaultValueProperty = NULL; + getRuntimeValuePropertyNames(m_eElementType, nClassId, pValueProperty, pDefaultValueProperty); + if ( pDefaultValueProperty && pValueProperty ) + { + sal_Bool bNonDefaultValuePropertyValue = sal_False; + // is the "value property" part of the sequence? + + // look up this property in our sequence + PropertyValueArray::iterator aEnd = m_aValues.end(); + for ( PropertyValueArray::iterator aCheck = m_aValues.begin(); + ( aCheck != aEnd ); + ++aCheck + ) + { + if ( aCheck->Name.equalsAscii( pDefaultValueProperty ) ) + bRestoreValuePropertyValue = sal_True; + else if ( aCheck->Name.equalsAscii( pValueProperty ) ) + { + bNonDefaultValuePropertyValue = sal_True; + // we need to restore the value property we found here, nothing else + aValuePropertyValue = aCheck->Value; + } + } + + if ( bRestoreValuePropertyValue && !bNonDefaultValuePropertyValue ) + { + // found it -> need to remember (and restore) the "value property value", which is not set explicitly + try + { + aValuePropertyValue = m_xElement->getPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the current value property!" ); + } + } + } + + // let the base class set all the values + OElementImport::EndElement(); + + // restore the "value property value", if necessary + if ( bRestoreValuePropertyValue && pValueProperty ) + { + try + { + m_xElement->setPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ), aValuePropertyValue ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while restoring the value property!" ); + } + } + + // the external cell binding, if applicable + if ( m_xElement.is() && m_sBoundCellAddress.getLength() ) + doRegisterCellValueBinding( m_sBoundCellAddress ); + + // XForms binding, if applicable + if ( m_xElement.is() && m_sBindingID.getLength() ) + doRegisterXFormsValueBinding( m_sBindingID ); + + // XForms list binding, if applicable + if ( m_xElement.is() && m_sListBindingID.getLength() ) + doRegisterXFormsListBinding( m_sListBindingID ); + + // XForms submission, if applicable + if ( m_xElement.is() && m_sSubmissionID.getLength() ) + doRegisterXFormsSubmission( m_sSubmissionID ); + } + + //--------------------------------------------------------------------- + void OControlImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress ) + { + OSL_PRECOND( m_xElement.is(), "OControlImport::doRegisterCellValueBinding: invalid element!" ); + OSL_PRECOND( _rBoundCellAddress.getLength(), + "OControlImport::doRegisterCellValueBinding: invalid address!" ); + + m_rContext.registerCellValueBinding( m_xElement, _rBoundCellAddress ); + } + + //--------------------------------------------------------------------- + void OControlImport::doRegisterXFormsValueBinding( const ::rtl::OUString& _rBindingID ) + { + OSL_PRECOND( m_xElement.is(), "need element" ); + OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" ); + + m_rContext.registerXFormsValueBinding( m_xElement, _rBindingID ); + } + + //--------------------------------------------------------------------- + void OControlImport::doRegisterXFormsListBinding( const ::rtl::OUString& _rBindingID ) + { + OSL_PRECOND( m_xElement.is(), "need element" ); + OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" ); + + m_rContext.registerXFormsListBinding( m_xElement, _rBindingID ); + } + + //--------------------------------------------------------------------- + void OControlImport::doRegisterXFormsSubmission( const ::rtl::OUString& _rSubmissionID ) + { + OSL_PRECOND( m_xElement.is(), "need element" ); + OSL_PRECOND( _rSubmissionID.getLength() > 0, "binding ID is not valid" ); + + m_rContext.registerXFormsSubmission( m_xElement, _rSubmissionID ); + } + + //--------------------------------------------------------------------- + //added by BerryJia for fixing bug102407 2002-11-5 + Reference< XPropertySet > OControlImport::createElement() + { + const Reference<XPropertySet> xPropSet = OElementImport::createElement(); + if ( xPropSet.is() ) + { + m_xInfo = xPropSet->getPropertySetInfo(); + if ( m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_ALIGN) ) + { + Any aValue; + xPropSet->setPropertyValue(PROPERTY_ALIGN,aValue); + } + } + return xPropSet; + } + + //===================================================================== + //= OImagePositionImport + //===================================================================== + //--------------------------------------------------------------------- + OImagePositionImport::OImagePositionImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, + sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType ) + :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) + ,m_nImagePosition( -1 ) + ,m_nImageAlign( 0 ) + ,m_bHaveImagePosition( sal_False ) + { + } + + //--------------------------------------------------------------------- + void OImagePositionImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue ) + { + if ( _rLocalName == GetXMLToken( XML_IMAGE_POSITION ) ) + { + OSL_VERIFY( PropertyConversion::convertString( + m_rContext.getGlobalContext(), ::getCppuType( &m_nImagePosition ), + _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImagePosition ) + ) >>= m_nImagePosition ); + m_bHaveImagePosition = sal_True; + } + else if ( _rLocalName == GetXMLToken( XML_IMAGE_ALIGN ) ) + { + OSL_VERIFY( PropertyConversion::convertString( + m_rContext.getGlobalContext(), ::getCppuType( &m_nImageAlign ), + _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImageAlign ) + ) >>= m_nImageAlign ); + } + else + OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); + } + + //--------------------------------------------------------------------- + void OImagePositionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OControlImport::StartElement( _rxAttrList ); + + if ( m_bHaveImagePosition ) + { + sal_Int16 nUnoImagePosition = ImagePosition::Centered; + if ( m_nImagePosition >= 0 ) + { + OSL_ENSURE( ( m_nImagePosition <= 3 ) && ( m_nImageAlign >= 0 ) && ( m_nImageAlign < 3 ), + "OImagePositionImport::StartElement: unknown image align and/or position!" ); + nUnoImagePosition = m_nImagePosition * 3 + m_nImageAlign; + } + + PropertyValue aImagePosition; + aImagePosition.Name = PROPERTY_IMAGE_POSITION; + aImagePosition.Value <<= nUnoImagePosition; + implPushBackPropertyValue( aImagePosition ); + } + } + + //===================================================================== + //= OReferredControlImport + //===================================================================== + //--------------------------------------------------------------------- + OReferredControlImport::OReferredControlImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType ) + :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) + { + } + + //--------------------------------------------------------------------- + void OReferredControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OControlImport::StartElement(_rxAttrList); + + // the base class should have created the control, so we can register it + if ( m_sReferringControls.getLength() ) + m_rFormImport.registerControlReferences(m_xElement, m_sReferringControls); + } + + //--------------------------------------------------------------------- + void OReferredControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue) + { + static const ::rtl::OUString s_sReferenceAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_FOR)); + if (_rLocalName == s_sReferenceAttributeName) + m_sReferringControls = _rValue; + else + OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + + //===================================================================== + //= OPasswordImport + //===================================================================== + //--------------------------------------------------------------------- + OPasswordImport::OPasswordImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) + :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + { + } + + //--------------------------------------------------------------------- + void OPasswordImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + static const ::rtl::OUString s_sEchoCharAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getSpecialAttributeName(SCA_ECHO_CHAR)); + if (_rLocalName == s_sEchoCharAttributeName) + { + // need a special handling for the EchoChar property + PropertyValue aEchoChar; + aEchoChar.Name = PROPERTY_ECHOCHAR; + OSL_ENSURE(_rValue.getLength() == 1, "OPasswordImport::handleAttribute: invalid echo char attribute!"); + // we ourself should not have written values other than of length 1 + if (_rValue.getLength() >= 1) + aEchoChar.Value <<= (sal_Int16)_rValue.getStr()[0]; + else + aEchoChar.Value <<= (sal_Int16)0; + implPushBackPropertyValue(aEchoChar); + } + else + OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + + //===================================================================== + //= ORadioImport + //===================================================================== + //--------------------------------------------------------------------- + ORadioImport::ORadioImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) + :OImagePositionImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) + { + } + + //--------------------------------------------------------------------- + void ORadioImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + // need special handling for the State & CurrentState properties: + // they're stored as booleans, but expected to be int16 properties + static const sal_Char* pCurrentSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED); + static const sal_Char* pSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED); + if ( _rLocalName.equalsAscii( pCurrentSelectedAttributeName ) + || _rLocalName.equalsAscii( pSelectedAttributeName ) + ) + { + const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName); + OSL_ENSURE(pProperty, "ORadioImport::handleAttribute: invalid property map!"); + if (pProperty) + { + const Any aBooleanValue( PropertyConversion::convertString(m_rContext.getGlobalContext(), pProperty->aPropertyType, _rValue, pProperty->pEnumMap) ); + + // create and store a new PropertyValue + PropertyValue aNewValue; + aNewValue.Name = pProperty->sPropertyName; + aNewValue.Value <<= (sal_Int16)::cppu::any2bool(aBooleanValue); + + implPushBackPropertyValue(aNewValue); + } + } + else + OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); + } + + //===================================================================== + //= OURLReferenceImport + //===================================================================== + OURLReferenceImport::OURLReferenceImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :OImagePositionImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + { + } + + //--------------------------------------------------------------------- + void OURLReferenceImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + static const sal_Char* s_pTargetLocationAttributeName = OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION ); + static const sal_Char* s_pImageDataAttributeName = OAttributeMetaData::getCommonControlAttributeName( CCA_IMAGE_DATA ); + + // need to make the URL absolute if + // * it's the image-data attribute + // * it's the target-location attribute, and we're dealign with an object which has the respective property + sal_Bool bMakeAbsolute = + ( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) ) + || ( ( 0 == _rLocalName.compareToAscii( s_pTargetLocationAttributeName ) ) + && ( ( OControlElement::BUTTON == m_eElementType ) + || ( OControlElement::IMAGE == m_eElementType ) + ) + ); + + if ( bMakeAbsolute && ( _rValue.getLength() > 0 ) ) + { + // make a global URL out of the local one + ::rtl::OUString sAdjustedValue; + // only resolve image related url + // we don't want say form url targets to be resolved + // using ResolveGraphicObjectURL + if ( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) ) + sAdjustedValue = m_rContext.getGlobalContext().ResolveGraphicObjectURL( _rValue, FALSE ); + else + sAdjustedValue = m_rContext.getGlobalContext().GetAbsoluteReference( _rValue ); + OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, sAdjustedValue ); + } + else + OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); + } + + //===================================================================== + //= OButtonImport + //===================================================================== + //--------------------------------------------------------------------- + OButtonImport::OButtonImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :OURLReferenceImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + { + enableTrackAttributes(); + } + + //--------------------------------------------------------------------- + void OButtonImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OURLReferenceImport::StartElement(_rxAttrList); + + // handle the target-frame attribute + simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank"); + } + + //===================================================================== + //= OValueRangeImport + //===================================================================== + //--------------------------------------------------------------------- + OValueRangeImport::OValueRangeImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType ) + :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) + ,m_nStepSizeValue( 1 ) + { + + } + + //--------------------------------------------------------------------- + void OValueRangeImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue ) + { + if ( _rLocalName.equalsAscii( OAttributeMetaData::getSpecialAttributeName( SCA_STEP_SIZE ) ) ) + { + GetImport().GetMM100UnitConverter().convertNumber( m_nStepSizeValue, _rValue ); + } + else + OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); + } + + //--------------------------------------------------------------------- + void OValueRangeImport::StartElement( const Reference< sax::XAttributeList >& _rxAttrList ) + { + OControlImport::StartElement( _rxAttrList ); + + if ( m_xInfo.is() ) + { + if ( m_xInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) ) + m_xElement->setPropertyValue( PROPERTY_SPIN_INCREMENT, makeAny( m_nStepSizeValue ) ); + else if ( m_xInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) ) + m_xElement->setPropertyValue( PROPERTY_LINE_INCREMENT, makeAny( m_nStepSizeValue ) ); + } + } + + //===================================================================== + //= OTextLikeImport + //===================================================================== + //--------------------------------------------------------------------- + OTextLikeImport::OTextLikeImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + ,m_bEncounteredTextPara( false ) + { + enableTrackAttributes(); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OTextLikeImport::CreateChildContext( sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList ) + { + if ( ( XML_NAMESPACE_TEXT == _nPrefix ) && _rLocalName.equalsIgnoreAsciiCaseAscii( "p" ) ) + { + OSL_ENSURE( m_eElementType == OControlElement::TEXT_AREA, + "OTextLikeImport::CreateChildContext: text paragraphs in a non-text-area?" ); + + if ( m_eElementType == OControlElement::TEXT_AREA ) + { + Reference< XText > xTextElement( m_xElement, UNO_QUERY ); + if ( xTextElement.is() ) + { + UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() ); + + if ( !m_xCursor.is() ) + { + m_xOldCursor = xTextImportHelper->GetCursor(); + m_xCursor = xTextElement->createTextCursor(); + + if ( m_xCursor.is() ) + xTextImportHelper->SetCursor( m_xCursor ); + } + if ( m_xCursor.is() ) + { + m_bEncounteredTextPara = true; + return xTextImportHelper->CreateTextChildContext( m_rContext.getGlobalContext(), _nPrefix, _rLocalName, _rxAttrList ); + } + } + else + { + // in theory, we could accumulate all the text portions (without formatting), + // and set it as Text property at the model ... + } + } + } + + return OControlImport::CreateChildContext( _nPrefix, _rLocalName, _rxAttrList ); + } + + //--------------------------------------------------------------------- + void OTextLikeImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OControlImport::StartElement(_rxAttrList); + + // handle the convert-empty-to-null attribute, whose default is different from the property default + // unfortunately, different classes are imported by this class ('cause they're represented by the + // same XML element), though not all of them know this property. + // So we have to do a check ... + if (m_xElement.is() && m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_EMPTY_IS_NULL) ) + simulateDefaultedAttribute(OAttributeMetaData::getDatabaseAttributeName(DA_CONVERT_EMPTY), PROPERTY_EMPTY_IS_NULL, "false"); + } + + //--------------------------------------------------------------------- + struct EqualHandle : public ::std::unary_function< PropertyValue, bool > + { + const sal_Int32 m_nHandle; + EqualHandle( sal_Int32 _nHandle ) : m_nHandle( _nHandle ) { } + + inline bool operator()( const PropertyValue& _rProp ) + { + return _rProp.Handle == m_nHandle; + } + }; + + //--------------------------------------------------------------------- + void OTextLikeImport::removeRedundantCurrentValue() + { + if ( m_bEncounteredTextPara ) + { + // In case the text is written in the text:p elements, we need to ignore what we read as + // current-value attribute, since it's redundant. + // fortunately, OElementImport tagged the value property with the PROPID_CURRENT_VALUE + // handle, so we do not need to determine the name of our value property here + // (normally, it should be "Text", since no other controls than the edit field should + // have the text:p elements) + PropertyValueArray::iterator aValuePropertyPos = ::std::find_if( + m_aValues.begin(), + m_aValues.end(), + EqualHandle( PROPID_CURRENT_VALUE ) + ); + if ( aValuePropertyPos != m_aValues.end() ) + { + OSL_ENSURE( aValuePropertyPos->Name == PROPERTY_TEXT, "OTextLikeImport::EndElement: text:p was present, but our value property is *not* 'Text'!" ); + if ( aValuePropertyPos->Name == PROPERTY_TEXT ) + { + ::std::copy( + aValuePropertyPos + 1, + m_aValues.end(), + aValuePropertyPos + ); + m_aValues.resize( m_aValues.size() - 1 ); + } + } + + // additionally, we need to set the "RichText" property of our element to TRUE + // (the presence of the text:p is used as indicator for the value of the RichText property) + sal_Bool bHasRichTextProperty = sal_False; + if ( m_xInfo.is() ) + bHasRichTextProperty = m_xInfo->hasPropertyByName( PROPERTY_RICH_TEXT ); + OSL_ENSURE( bHasRichTextProperty, "OTextLikeImport::EndElement: text:p, but no rich text control?" ); + if ( bHasRichTextProperty ) + m_xElement->setPropertyValue( PROPERTY_RICH_TEXT, makeAny( (sal_Bool)sal_True ) ); + } + // Note that we do *not* set the RichText property (in case our element has one) to sal_False here + // since this is the default of this property, anyway. + } + + //--------------------------------------------------------------------- + struct EqualName : public ::std::unary_function< PropertyValue, bool > + { + const ::rtl::OUString m_sName; + EqualName( const ::rtl::OUString& _rName ) : m_sName( _rName ) { } + + inline bool operator()( const PropertyValue& _rProp ) + { + return _rProp.Name == m_sName; + } + }; + + //--------------------------------------------------------------------- + void OTextLikeImport::adjustDefaultControlProperty() + { + // In OpenOffice.org 2.0, we changed the implementation of the css.form.component.TextField (the model of a text field control), + // so that it now uses another default control. So if we encounter a text field where the *old* default + // control property is writting, we are not allowed to use it + PropertyValueArray::iterator aDefaultControlPropertyPos = ::std::find_if( + m_aValues.begin(), + m_aValues.end(), + EqualName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultControl" ) ) ) + ); + if ( aDefaultControlPropertyPos != m_aValues.end() ) + { + ::rtl::OUString sDefaultControl; + OSL_VERIFY( aDefaultControlPropertyPos->Value >>= sDefaultControl ); + if ( sDefaultControl.equalsAscii( "stardiv.one.form.control.Edit" ) ) + { + // complete remove this property value from the array. Today's "default value" of the "DefaultControl" + // property is sufficient + ::std::copy( + aDefaultControlPropertyPos + 1, + m_aValues.end(), + aDefaultControlPropertyPos + ); + m_aValues.resize( m_aValues.size() - 1 ); + } + } + } + + //--------------------------------------------------------------------- + void OTextLikeImport::EndElement() + { + removeRedundantCurrentValue(); + adjustDefaultControlProperty(); + + // let the base class do the stuff + OControlImport::EndElement(); + + // some cleanups + UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() ); + if ( m_xCursor.is() ) + { + // delete the newline which has been imported errornously + // TODO (fs): stole this code somewhere - why don't we fix the text import?? + m_xCursor->gotoEnd( sal_False ); + m_xCursor->goLeft( 1, sal_True ); + m_xCursor->setString( ::rtl::OUString() ); + + // reset cursor + xTextImportHelper->ResetCursor(); + } + + if ( m_xOldCursor.is() ) + xTextImportHelper->SetCursor( m_xOldCursor ); + + } + + //===================================================================== + //= OListAndComboImport + //===================================================================== + //--------------------------------------------------------------------- + OListAndComboImport::OListAndComboImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + ,m_nEmptyListItems( 0 ) + ,m_nEmptyValueItems( 0 ) + ,m_bEncounteredLSAttrib( sal_False ) + ,m_bLinkWithIndexes( sal_False ) + { + if (OControlElement::COMBOBOX == m_eElementType) + enableTrackAttributes(); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OListAndComboImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList) + { + // is it the "option" sub tag of a listbox ? + static const ::rtl::OUString s_sOptionElementName = ::rtl::OUString::createFromAscii("option"); + if (s_sOptionElementName == _rLocalName) + return new OListOptionImport(GetImport(), _nPrefix, _rLocalName, this); + + // is it the "item" sub tag of a combobox ? + static const ::rtl::OUString s_sItemElementName = ::rtl::OUString::createFromAscii("item"); + if (s_sItemElementName == _rLocalName) + return new OComboItemImport(GetImport(), _nPrefix, _rLocalName, this); + + // everything else + return OControlImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + m_bLinkWithIndexes = sal_False; + + OControlImport::StartElement(_rxAttrList); + + if (OControlElement::COMBOBOX == m_eElementType) + { + // for the auto-completion + // the attribute default does not equal the property default, so in case we did not read this attribute, + // we have to simulate it + simulateDefaultedAttribute( OAttributeMetaData::getSpecialAttributeName( SCA_AUTOMATIC_COMPLETION ), PROPERTY_AUTOCOMPLETE, "false"); + + // same for the convert-empty-to-null attribute, which's default is different from the property default + simulateDefaultedAttribute( OAttributeMetaData::getDatabaseAttributeName( DA_CONVERT_EMPTY ), PROPERTY_EMPTY_IS_NULL, "false"); + } + } + + //--------------------------------------------------------------------- + void OListAndComboImport::EndElement() + { + // append the list source property the the properties sequence of our importer + // the string item list + PropertyValue aItemList; + aItemList.Name = PROPERTY_STRING_ITEM_LIST; + aItemList.Value <<= m_aListSource; + implPushBackPropertyValue(aItemList); + + if (OControlElement::LISTBOX == m_eElementType) + { + OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems), + "OListAndComboImport::EndElement: inconsistence between labels and values!"); + + if ( !m_bEncounteredLSAttrib ) + { + // the value sequence + PropertyValue aValueList; + aValueList.Name = PROPERTY_LISTSOURCE; + aValueList.Value <<= m_aValueList; + implPushBackPropertyValue(aValueList); + } + + // the select sequence + PropertyValue aSelected; + aSelected.Name = PROPERTY_SELECT_SEQ; + aSelected.Value <<= m_aSelectedSeq; + implPushBackPropertyValue(aSelected); + + // the default select sequence + PropertyValue aDefaultSelected; + aDefaultSelected.Name = PROPERTY_DEFAULT_SELECT_SEQ; + aDefaultSelected.Value <<= m_aDefaultSelectedSeq; + implPushBackPropertyValue(aDefaultSelected); + } + + OControlImport::EndElement(); + + // the external list source, if applicable + if ( m_xElement.is() && m_sCellListSource.getLength() ) + m_rContext.registerCellRangeListSource( m_xElement, m_sCellListSource ); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress ) + { + ::rtl::OUString sBoundCellAddress( _rBoundCellAddress ); + if ( m_bLinkWithIndexes ) + { + // This is a HACK. We register a string which is no valid address, but allows + // (somewhere else) to determine that a non-standard binding should be created. + // This hack is acceptable for OOo 1.1.1, since the file format for value + // bindings of form controls is to be changed afterwards, anyway. + sBoundCellAddress += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":index" ) ); + } + + OControlImport::doRegisterCellValueBinding( sBoundCellAddress ); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + static const sal_Char* pListSourceAttributeName = OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE); + if ( _rLocalName.equalsAscii(pListSourceAttributeName) ) + { + PropertyValue aListSource; + aListSource.Name = PROPERTY_LISTSOURCE; + + // it's the ListSource attribute + m_bEncounteredLSAttrib = sal_True; + if ( OControlElement::COMBOBOX == m_eElementType ) + { + aListSource.Value <<= _rValue; + } + else + { + // a listbox which has a list-source attribute must have a list-source-type of something + // not equal to ValueList. + // In this case, the list-source value is simply the one and only element of the ListSource property. + Sequence< ::rtl::OUString > aListSourcePropValue( 1 ); + aListSourcePropValue[0] = _rValue; + aListSource.Value <<= aListSourcePropValue; + } + + implPushBackPropertyValue( aListSource ); + } + else if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_CELL_RANGE ) ) ) + { + m_sCellListSource = _rValue; + } + else if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_LINKING_TYPE ) ) ) + { + sal_Int16 nLinkageType = 0; + PropertyConversion::convertString( + m_rContext.getGlobalContext(), + ::getCppuType( static_cast< sal_Int16* >( NULL ) ), + _rValue, + OEnumMapper::getEnumMap( OEnumMapper::epListLinkageType ) + ) >>= nLinkageType; + + m_bLinkWithIndexes = ( nLinkageType != 0 ); + } + else + OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implPushBackLabel(const ::rtl::OUString& _rLabel) + { + OSL_ENSURE(!m_nEmptyListItems, "OListAndComboImport::implPushBackValue: label list is already done!"); + if (!m_nEmptyListItems) + pushBackSequenceElement(m_aListSource, _rLabel); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implPushBackValue(const ::rtl::OUString& _rValue) + { + OSL_ENSURE(!m_nEmptyValueItems, "OListAndComboImport::implPushBackValue: value list is already done!"); + if (!m_nEmptyValueItems) + { + OSL_ENSURE( !m_bEncounteredLSAttrib, "OListAndComboImport::implPushBackValue: invalid structure! Did you save this document with a version prior SRC641 m?" ); + // We already had the list-source attribute, which means that the ListSourceType is + // not ValueList, which means that the ListSource should contain only one string in + // the first element of the sequence + // All other values in the file are invalid + + pushBackSequenceElement( m_aValueList, _rValue ); + } + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implEmptyLabelFound() + { + ++m_nEmptyListItems; + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implEmptyValueFound() + { + ++m_nEmptyValueItems; + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implSelectCurrentItem() + { + OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems), + "OListAndComboImport::implSelectCurrentItem: inconsistence between labels and values!"); + + sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems); + pushBackSequenceElement(m_aSelectedSeq, nItemNumber); + } + + //--------------------------------------------------------------------- + void OListAndComboImport::implDefaultSelectCurrentItem() + { + OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems), + "OListAndComboImport::implDefaultSelectCurrentItem: inconsistence between labels and values!"); + + sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems); + pushBackSequenceElement(m_aDefaultSelectedSeq, nItemNumber); + } + + //===================================================================== + //= OListOptionImport + //===================================================================== + //--------------------------------------------------------------------- + OListOptionImport::OListOptionImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OListAndComboImportRef& _rListBox) + :SvXMLImportContext(_rImport, _nPrefix, _rName) + ,m_xListBoxImport(_rListBox) + { + } + + //--------------------------------------------------------------------- + void OListOptionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + // the label and the value + const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap(); + const ::rtl::OUString sLabelAttribute = rMap.GetQNameByKey( + GetPrefix(), ::rtl::OUString::createFromAscii("label")); + const ::rtl::OUString sValueAttribute = rMap.GetQNameByKey( + GetPrefix(), ::rtl::OUString::createFromAscii("value")); + + // ------------------- + // the label attribute + ::rtl::OUString sValue = _rxAttrList->getValueByName(sLabelAttribute); + sal_Bool bNonexistentAttribute = sal_False; + if (!sValue.getLength()) + if (0 == _rxAttrList->getTypeByName(sLabelAttribute).getLength()) + // this attribute does not really exist + bNonexistentAttribute = sal_True; + + if (bNonexistentAttribute) + m_xListBoxImport->implEmptyLabelFound(); + else + m_xListBoxImport->implPushBackLabel( sValue ); + + // ------------------- + // the value attribute + sValue = _rxAttrList->getValueByName(sValueAttribute); + bNonexistentAttribute = sal_False; + if (!sValue.getLength()) + if (0 == _rxAttrList->getTypeByName(sValueAttribute).getLength()) + // this attribute does not really exist + bNonexistentAttribute = sal_True; + + if (bNonexistentAttribute) + m_xListBoxImport->implEmptyValueFound(); + else + m_xListBoxImport->implPushBackValue( sValue ); + + // the current-selected and selected + const ::rtl::OUString sSelectedAttribute = rMap.GetQNameByKey( + GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED))); + const ::rtl::OUString sDefaultSelectedAttribute = rMap.GetQNameByKey( + GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED))); + + // propagate the selected flag + sal_Bool bSelected; + GetImport().GetMM100UnitConverter().convertBool(bSelected, _rxAttrList->getValueByName(sSelectedAttribute)); + if (bSelected) + m_xListBoxImport->implSelectCurrentItem(); + + // same for the default selected + sal_Bool bDefaultSelected; + GetImport().GetMM100UnitConverter().convertBool(bDefaultSelected, _rxAttrList->getValueByName(sDefaultSelectedAttribute)); + if (bDefaultSelected) + m_xListBoxImport->implDefaultSelectCurrentItem(); + + SvXMLImportContext::StartElement(_rxAttrList); + } + + //===================================================================== + //= OComboItemImport + //===================================================================== + //--------------------------------------------------------------------- + OComboItemImport::OComboItemImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OListAndComboImportRef& _rListBox) + :SvXMLImportContext(_rImport, _nPrefix, _rName) + ,m_xListBoxImport(_rListBox) + { + } + + //--------------------------------------------------------------------- + void OComboItemImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + const ::rtl::OUString sLabelAttributeName = GetImport().GetNamespaceMap().GetQNameByKey( + GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL))); + m_xListBoxImport->implPushBackLabel(_rxAttrList->getValueByName(sLabelAttributeName)); + + SvXMLImportContext::StartElement(_rxAttrList); + } + + + //===================================================================== + //= OColumnWrapperImport + //===================================================================== + //--------------------------------------------------------------------- + OColumnWrapperImport::OColumnWrapperImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer) + :SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName) + ,m_xParentContainer(_rxParentContainer) + ,m_rFormImport(_rImport) + ,m_rEventManager(_rEventManager) + { + } + //--------------------------------------------------------------------- + SvXMLImportContext* OColumnWrapperImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >&) + { + OControlImport* pReturn = implCreateChildContext(_nPrefix, _rLocalName, OElementNameMap::getElementType(_rLocalName)); + if (pReturn) + { + OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::CreateChildContext: had no form:column element!"); + pReturn->addOuterAttributes(m_xOwnAttributes); + } + return pReturn; + } + //--------------------------------------------------------------------- + void OColumnWrapperImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OSL_ENSURE(!m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: aready have the cloned list!"); + + // clone the attributes + Reference< XCloneable > xCloneList(_rxAttrList, UNO_QUERY); + OSL_ENSURE(xCloneList.is(), "OColumnWrapperImport::StartElement: AttributeList not cloneable!"); + if ( xCloneList.is() ) + m_xOwnAttributes = Reference< sax::XAttributeList >(xCloneList->createClone(), UNO_QUERY); + OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: no cloned list!"); + } + + //--------------------------------------------------------------------- + OControlImport* OColumnWrapperImport::implCreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + OControlElement::ElementType _eType) + { + OSL_ENSURE( (OControlElement::TEXT == _eType) + || (OControlElement::TEXT_AREA == _eType) + || (OControlElement::FORMATTED_TEXT == _eType) + || (OControlElement::CHECKBOX == _eType) + || (OControlElement::LISTBOX == _eType) + || (OControlElement::COMBOBOX == _eType), + "OColumnWrapperImport::implCreateChildContext: invalid or unrecognized sub element!"); + + switch (_eType) + { + case OControlElement::COMBOBOX: + case OControlElement::LISTBOX: + return new OColumnImport<OListAndComboImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); + + case OControlElement::PASSWORD: + return new OColumnImport<OPasswordImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); + + case OControlElement::TEXT: + case OControlElement::TEXT_AREA: + case OControlElement::FORMATTED_TEXT: + return new OColumnImport< OTextLikeImport >( m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); + + default: + return new OColumnImport<OControlImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); + } + } + + //===================================================================== + //= OGridImport + //===================================================================== + //--------------------------------------------------------------------- + OGridImport::OGridImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :OGridImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "column") + { + setElementType(_eType); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OGridImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName) + { + return new OColumnWrapperImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer); + } + + //===================================================================== + //= OFormImport + //===================================================================== + //--------------------------------------------------------------------- + OFormImport::OFormImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const Reference< XNameContainer >& _rxParentContainer) + :OFormImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "control") + { + enableTrackAttributes(); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OFormImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList) + { + if( token::IsXMLToken(_rLocalName, token::XML_FORM) ) + return new OFormImport( m_rFormImport, *this, _nPrefix, _rLocalName, + m_xMeAsContainer); + else if ( token::IsXMLToken(_rLocalName, token::XML_CONNECTION_RESOURCE) ) + return new OXMLDataSourceImport(GetImport(), _nPrefix, _rLocalName, _rxAttrList,m_xElement); + else if( (token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) && + (XML_NAMESPACE_OFFICE == _nPrefix)) || + token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) ) + return OElementImport::CreateChildContext( _nPrefix, _rLocalName, + _rxAttrList ); + else + return implCreateChildContext( _nPrefix, _rLocalName, + OElementNameMap::getElementType(_rLocalName) ); + } + + //--------------------------------------------------------------------- + void OFormImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + m_rFormImport.enterEventContext(); + OFormImport_Base::StartElement(_rxAttrList); + + // handle the target-frame attribute + simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank"); + } + + //--------------------------------------------------------------------- + void OFormImport::EndElement() + { + OFormImport_Base::EndElement(); + m_rFormImport.leaveEventContext(); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OFormImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName) + { + OSL_ENSURE( !this, "illegal call to OFormImport::implCreateControlWrapper" ); + return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName ); + } + + //--------------------------------------------------------------------- + void OFormImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) + { + // handle the master/details field attributes (they're way too special to let the OPropertyImport handle them) + static const ::rtl::OUString s_sMasterFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faMasterFields)); + static const ::rtl::OUString s_sDetailFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faDetailFiels)); + + if (s_sMasterFieldsAttributeName == _rLocalName) + implTranslateStringListProperty(PROPERTY_MASTERFIELDS, _rValue); + else if (s_sDetailFieldsAttributeName == _rLocalName) + implTranslateStringListProperty(PROPERTY_DETAILFIELDS, _rValue); + + else + OFormImport_Base::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); + } + + //--------------------------------------------------------------------- + void OFormImport::implTranslateStringListProperty(const ::rtl::OUString& _rPropertyName, const ::rtl::OUString& _rValue) + { + PropertyValue aProp; + aProp.Name = _rPropertyName; + + Sequence< ::rtl::OUString > aList; + + // split up the value string + if (_rValue.getLength()) + { + // For the moment, we build a vector instead of a Sequence. It's easier to handle because of it's + // push_back method + ::std::vector< ::rtl::OUString > aElements; + // estimate the number of tokens + sal_Int32 nEstimate = 0, nLength = _rValue.getLength(); + const sal_Unicode* pChars = _rValue.getStr(); + for (sal_Int32 i=0; i<nLength; ++i, ++pChars) + if (*pChars == ',') + ++nEstimate; + aElements.reserve(nEstimate + 1); + // that's the worst case. If the string contains the separator character _quoted_, we reserved to much ... + + + sal_Int32 nElementStart = 0; + sal_Int32 nNextSep = 0; + sal_Int32 nElementLength; + ::rtl::OUString sElement; + do + { + // extract the current element + nNextSep = SvXMLUnitConverter::indexOfComma( + _rValue, nElementStart); + if (-1 == nNextSep) + nNextSep = nLength; + sElement = _rValue.copy(nElementStart, nNextSep - nElementStart); + + nElementLength = sElement.getLength(); + // when writing the sequence, we quoted the single elements with " characters + OSL_ENSURE( (nElementLength >= 2) + && (sElement.getStr()[0] == '"') + && (sElement.getStr()[nElementLength - 1] == '"'), + "OFormImport::implTranslateStringListProperty: invalid quoted element name."); + sElement = sElement.copy(1, nElementLength - 2); + + aElements.push_back(sElement); + + // swith to the next element + nElementStart = 1 + nNextSep; + } + while (nElementStart < nLength); + + ::rtl::OUString *pElements = aElements.empty() ? 0 : &aElements[0]; + aList = Sequence< ::rtl::OUString >(pElements, aElements.size()); + } + else + { + OSL_ENSURE(sal_False, "OFormImport::implTranslateStringListProperty: invalid value (empty)!"); + } + + aProp.Value <<= aList; + + // add the property to the base class' array + implPushBackPropertyValue(aProp); + } + //===================================================================== + //= OXMLDataSourceImport + //===================================================================== + OXMLDataSourceImport::OXMLDataSourceImport( + SvXMLImport& _rImport + ,sal_uInt16 nPrfx + , const ::rtl::OUString& _sLocalName + ,const Reference< ::com::sun::star::xml::sax::XAttributeList > & _xAttrList + ,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xElement) : + SvXMLImportContext( _rImport, nPrfx, _sLocalName ) + { + OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!"); + const SvXMLNamespaceMap& rMap = _rImport.GetNamespaceMap(); + + sal_Int16 nLength = (_xElement.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0; + for(sal_Int16 i = 0; i < nLength; ++i) + { + ::rtl::OUString sLocalName; + ::rtl::OUString sAttrName = _xAttrList->getNameByIndex( i ); + sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName, &sLocalName ); + + if ( ( nPrefix == OAttributeMetaData::getCommonControlAttributeNamespace( CCA_TARGET_LOCATION ) ) + && ( sLocalName.equalsAscii( OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION ) ) ) + ) + { + ::rtl::OUString sValue = _xAttrList->getValueByIndex( i ); + + INetURLObject aURL(sValue); + if ( aURL.GetProtocol() == INET_PROT_FILE ) + _xElement->setPropertyValue(PROPERTY_DATASOURCENAME,makeAny(sValue)); + else + _xElement->setPropertyValue(PROPERTY_URL,makeAny(sValue)); // the url is the "sdbc:" string + break; + } + } + } + //--------------------------------------------------------------------- + OControlImport* OFormImport::implCreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + OControlElement::ElementType _eType ) + { + switch (_eType) + { + case OControlElement::TEXT: + case OControlElement::TEXT_AREA: + case OControlElement::FORMATTED_TEXT: + return new OTextLikeImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::BUTTON: + case OControlElement::IMAGE: + case OControlElement::IMAGE_FRAME: + return new OButtonImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType ); + + case OControlElement::COMBOBOX: + case OControlElement::LISTBOX: + return new OListAndComboImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::RADIO: + return new ORadioImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::CHECKBOX: + return new OImagePositionImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::PASSWORD: + return new OPasswordImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::FRAME: + case OControlElement::FIXED_TEXT: + return new OReferredControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::GRID: + return new OGridImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + + case OControlElement::VALUERANGE: + return new OValueRangeImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType ); + + default: + return new OControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); + } + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/elementimport.hxx b/xmloff/source/forms/elementimport.hxx new file mode 100644 index 000000000000..97eb2ec950d3 --- /dev/null +++ b/xmloff/source/forms/elementimport.hxx @@ -0,0 +1,752 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_ELEMENTIMPORT_HXX_ +#define _XMLOFF_FORMS_ELEMENTIMPORT_HXX_ + +#include "propertyimport.hxx" +#include "controlelement.hxx" +#include "valueproperties.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/form/XGridColumnFactory.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +/** === end UNO includes === **/ +#include <comphelper/stl_types.hxx> +#include "eventimport.hxx" +#include "logging.hxx" + +class XMLTextStyleContext; +//......................................................................... +namespace xmloff +{ +//......................................................................... + + class IControlIdMap; + class OFormLayerXMLImport_Impl; + + //===================================================================== + //= OElementNameMap + //===================================================================== + const OControlElement::ElementType& operator ++(OControlElement::ElementType& _e); + + /** helper class which allows fast translation of xml tag names into element types. + */ + class OElementNameMap : public OControlElement + { + protected: + DECLARE_STL_USTRINGACCESS_MAP( ElementType, MapString2Element ); + static MapString2Element s_sElementTranslations; + + protected: + OElementNameMap() { } + + public: + static ElementType getElementType(const ::rtl::OUString& _rName); + }; + + //===================================================================== + //= OElementImport + //===================================================================== + /** implements common behaviour for importing forms, controls and columns + */ + class OElementImport + :public OPropertyImport + ,public IEventAttacher + ,public OStackedLogging + { + protected: + ::rtl::OUString m_sServiceName; // the service name as extracted from the service-name attribute + ::rtl::OUString m_sName; // the name of the object (redundant, already contained in the base class' array) + OFormLayerXMLImport_Impl& m_rFormImport; // the form import context + IEventAttacherManager& m_rEventManager; // the event attacher manager + + const XMLTextStyleContext* m_pStyleElement; // the XML element which describes the style we encountered + // while reading our element + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + m_xParentContainer; + // the parent container to insert the new element into + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > + m_xInfo; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xElement; // the element we're creating. Valid after StartElement + + public: + /** ctor + @param _rImport + the importer + @param _rEventManager + the event attacher manager for the control beeing imported + @param _nPrefix + the namespace prefix + @param _rName + the element name + @param _rAttributeMap + the attribute map to be used for translating attributes into properties + @param _rxParentContainer + the container in which the new element should be inserted + */ + OElementImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, + sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer + ); + virtual ~OElementImport(); + + protected: + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + + // IEventAttacher + virtual void registerEvents( + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ); + + /** create the (uninitialized) element which is to represent the read data + + <p>The default implementation uses <member>m_xORB</member> to create a object with <member>m_sServiceName</member>. + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + createElement(); + + protected: + /** can be used to handle properties where the attribute default and the property default differ. + <p>In such case, if the property had the attribute default upon writing, nothing is read, so upon reading, + the property is still at it's own default (which is not the attribute default).<p/> + <p>This method, if told the attribute and the property, and the (implied) attribute default, sets the + property value as if the attribute was encountered.</p> + @see encounteredAttribute + */ + void simulateDefaultedAttribute(const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, const sal_Char* _pAttributeDefault); + + private: + ::rtl::OUString implGetDefaultName() const; + void implImportGenericProperties(); + + /** sets the style properties which have been read for the element (if any) + */ + void implSetStyleProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject ); + }; + + //===================================================================== + //= OControlImport + //===================================================================== + /** helper class for importing the description of a single control + */ + class OControlImport + :public OElementImport + ,public OValuePropertiesMetaData + { + protected: + ::rtl::OUString m_sControlId; + OControlElement::ElementType m_eElementType; + + PropertyValueArray m_aValueProperties; + // the value properties (value, current-value, min-value, max-value) require some special + // handling + + // we fake the attributes our base class gets: we add the attributes of the outer wrapper + // element which encloses us + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > + m_xOuterAttributes; + + /** the address of the calc cell which the control model should be bound to, + if applicable + */ + ::rtl::OUString m_sBoundCellAddress; + + /** name of a value binding (xforms:bind attribute) */ + ::rtl::OUString m_sBindingID; + + /** name of a list binding (form:xforms-list-source attribute) */ + ::rtl::OUString m_sListBindingID; + + /** name of a submission (xforms:submission attribute) */ + ::rtl::OUString m_sSubmissionID; + + protected: + // for use by derived classes only + OControlImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, + sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer + ); + + public: + OControlImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, + sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + + void addOuterAttributes(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxOuterAttribs); + + protected: + void setElementType(OControlElement::ElementType _eType) { m_eElementType = _eType; } + + protected: + void implTranslateValueProperty( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >& _rxPropInfo, + ::com::sun::star::beans::PropertyValue& /* [in/out] */ _rPropValue); + + /** registers the given cell address as value binding address for our element + + <p>The default implementation simply calls registerCellValueBinding at our import + context, but you may want to override this behaviour.</p> + + @param _rBoundCellAddress + the cell address to register for our element. Must not be <NULL/>. + @precond + we have a valid element (m_xElement) + */ + virtual void doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress ); + + /** register the given XForms binding */ + virtual void doRegisterXFormsValueBinding( const ::rtl::OUString& ); + + /** register the given XForms list binding */ + virtual void doRegisterXFormsListBinding( const ::rtl::OUString& ); + + /** register the given XForms submission */ + virtual void doRegisterXFormsSubmission( const ::rtl::OUString& ); + + protected: + //added by BerryJia for fixing bug102407 2002-11-5 + // OElementImport overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + createElement(); + + }; + + // TODO: + // this whole mechanism doesn't scale. Instead of deriving even more classes for every new attribute, + // we should have dedicated attribute handlers + // The rest of xmloff implements it this way - why don't we do, too? + + //===================================================================== + //= OImagePositionImport + //===================================================================== + class OImagePositionImport : public OControlImport + { + sal_Int16 m_nImagePosition; + sal_Int16 m_nImageAlign; + sal_Bool m_bHaveImagePosition; + + public: + OImagePositionImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + protected: + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + + // OPropertyImport overridables + virtual void handleAttribute( sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue + ); + }; + + //===================================================================== + //= OReferredControlImport + //===================================================================== + class OReferredControlImport : public OControlImport + { + protected: + ::rtl::OUString m_sReferringControls; // the list of ids of controls referring to the one beeing imported + + public: + OReferredControlImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + }; + + //===================================================================== + //= OPasswordImport + //===================================================================== + class OPasswordImport : public OControlImport + { + public: + OPasswordImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + }; + + //===================================================================== + //= ORadioImport + //===================================================================== + class ORadioImport : public OImagePositionImport + { + public: + ORadioImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + protected: + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + }; + + //===================================================================== + //= OURLReferenceImport + //===================================================================== + /** a specialized version of the <type>OControlImport</type> class, which is able + to handle attributes which denote URLs (and stored relative) + */ + class OURLReferenceImport : public OImagePositionImport + { + public: + OURLReferenceImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + protected: + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + }; + + //===================================================================== + //= OButtonImport + //===================================================================== + /** A specialized version of the <type>OControlImport</type> class, which handles + the target frame for image and command buttons + */ + class OButtonImport : public OURLReferenceImport + { + public: + OButtonImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + protected: + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + }; + + //===================================================================== + //= OValueRangeImport + //===================================================================== + /** A specialized version of the <type>OControlImport</type> class, which imports + the value-range elements + */ + class OValueRangeImport : public OControlImport + { + private: + sal_Int32 m_nStepSizeValue; + + public: + OValueRangeImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + protected: + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList ); + + // OPropertyImport overridables + virtual void handleAttribute( sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue ); + }; + + //===================================================================== + //= OTextLikeImport + //===================================================================== + /** A specialized version of the <type>OControlImport</type> class, which handles + text like controls which have the convert-empty-to-null attribute</p> + */ + class OTextLikeImport : public OControlImport + { + private: + ::com::sun::star::uno::Reference< com::sun::star::text::XTextCursor > m_xCursor; + ::com::sun::star::uno::Reference< com::sun::star::text::XTextCursor > m_xOldCursor; + bool m_bEncounteredTextPara; + + public: + OTextLikeImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + private: + void adjustDefaultControlProperty(); + void removeRedundantCurrentValue(); + }; + + //===================================================================== + //= OListAndComboImport + //===================================================================== + /** A specialized version of the <type>OControlImport</type> class, which handles + attributes / sub elements which are special to list and combo boxes + */ + class OListAndComboImport : public OControlImport + { + friend class OListOptionImport; + friend class OComboItemImport; + + protected: + ::com::sun::star::uno::Sequence< ::rtl::OUString > + m_aListSource; + ::com::sun::star::uno::Sequence< ::rtl::OUString > + m_aValueList; + + ::com::sun::star::uno::Sequence< sal_Int16 > + m_aSelectedSeq; + ::com::sun::star::uno::Sequence< sal_Int16 > + m_aDefaultSelectedSeq; + + ::rtl::OUString m_sCellListSource; /// the cell range which acts as list source for the control + + sal_Int32 m_nEmptyListItems; /// number of empty list items encountered during reading + sal_Int32 m_nEmptyValueItems; /// number of empty value items encountered during reading + + sal_Bool m_bEncounteredLSAttrib; + sal_Bool m_bLinkWithIndexes; /** <TRUE/> if and only if we should use a cell value binding + which exchanges the selection index (instead of the selection text + */ + + public: + OListAndComboImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType + ); + + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + + // OControlImport ovrridables + virtual void doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress ); + + protected: + void implPushBackLabel(const ::rtl::OUString& _rLabel); + void implPushBackValue(const ::rtl::OUString& _rValue); + + void implEmptyLabelFound(); + void implEmptyValueFound(); + + void implSelectCurrentItem(); + void implDefaultSelectCurrentItem(); + }; + SV_DECL_IMPL_REF(OListAndComboImport); + + //===================================================================== + //= OListOptionImport + //===================================================================== + /** helper class for importing a single <form:option> element. + */ + class OListOptionImport + :public SvXMLImportContext + { + OListAndComboImportRef m_xListBoxImport; + + public: + OListOptionImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OListAndComboImportRef& _rListBox); + + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + }; + + //===================================================================== + //= OComboItemImport + //===================================================================== + /** helper class for importing a single <form:item> element. + */ + class OComboItemImport + :public SvXMLImportContext + { + OListAndComboImportRef m_xListBoxImport; + + public: + OComboItemImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OListAndComboImportRef& _rListBox); + + protected: + // SvXMLImportContext overridables + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + }; + + //===================================================================== + //= OContainerImport + //===================================================================== + // BASE must be a derivee of OElementImport + template <class BASE> + class OContainerImport + :public BASE + ,public ODefaultEventAttacherManager + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + m_xMeAsContainer; + ::rtl::OUString m_sWrapperElementName; + + protected: + OContainerImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + const sal_Char* _pWrapperElementName) + :BASE(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) + ,m_sWrapperElementName(::rtl::OUString::createFromAscii(_pWrapperElementName)) + { + } + + // SvXMLImportContext overridables + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + protected: + // OElementImport overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + createElement(); + + // create the child context for the given control type + virtual SvXMLImportContext* implCreateControlWrapper( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName) = 0; + }; + + //===================================================================== + //= OColumnImport + //===================================================================== + /** helper class importing a single grid column (without the <form:column> element wrapping + the column). + + <p>BASE (the template argument) must be a derivee of OControlImport</p> + */ + template <class BASE> + class OColumnImport : public BASE + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::form::XGridColumnFactory > + m_xColumnFactory; + + public: + OColumnImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType); + + protected: + // OElementImport overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + createElement(); + }; + + //===================================================================== + //= OColumnWrapperImport + //===================================================================== + class OColumnWrapperImport : public SvXMLImportContext + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > + m_xOwnAttributes; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + m_xParentContainer; + OFormLayerXMLImport_Impl& m_rFormImport; + IEventAttacherManager& m_rEventManager; + + public: + OColumnWrapperImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer); + + // SvXMLImportContext overridables + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + protected: + OControlImport* implCreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + OControlElement::ElementType _eType); + }; + + //===================================================================== + //= OGridImport + //===================================================================== + typedef OContainerImport< OControlImport > OGridImport_Base; + /** helper class importing a single <form:grid> element + */ + class OGridImport : public OGridImport_Base + { + public: + OGridImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType); + + protected: + // OContainerImport overridables + virtual SvXMLImportContext* implCreateControlWrapper( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName); + }; + + //===================================================================== + //= OFormImport + //===================================================================== + typedef OContainerImport< OElementImport > OFormImport_Base; + /** helper class importing a single <form:form> element + */ + class OFormImport : public OFormImport_Base + { + public: + OFormImport( + OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer + ); + + protected: + // SvXMLImportContext overridables + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void EndElement(); + + // OContainerImport overridables + virtual SvXMLImportContext* implCreateControlWrapper( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName); + + // OPropertyImport overridables + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + + OControlImport* implCreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + OControlElement::ElementType _eType ); + + + void implTranslateStringListProperty(const ::rtl::OUString& _rPropertyName, const ::rtl::OUString& _rValue); + }; + + //===================================================================== + //= OXMLDataSourceImport + //===================================================================== + class OXMLDataSourceImport : public SvXMLImportContext + { + public: + OXMLDataSourceImport( SvXMLImport& _rImport + ,sal_uInt16 nPrfx + ,const ::rtl::OUString& rLName + ,const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList + ,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xElement); + }; + +#define _INCLUDING_FROM_ELEMENTIMPORT_HXX_ +#include "elementimport_impl.hxx" +#undef _INCLUDING_FROM_ELEMENTIMPORT_HXX_ + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_ELEMENTIMPORT_HXX_ + diff --git a/xmloff/source/forms/elementimport_impl.hxx b/xmloff/source/forms/elementimport_impl.hxx new file mode 100644 index 000000000000..d110d7df8b33 --- /dev/null +++ b/xmloff/source/forms/elementimport_impl.hxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// no include protection. This file is included from elementimport.hxx only. + +#ifndef _INCLUDING_FROM_ELEMENTIMPORT_HXX_ +#error "do not include this file directly!" +#endif + +// no namespace. Same as above: this file is included from elementimport.hxx only, +// and this is done inside the namespace + +//========================================================================= +//= OContainerImport +//========================================================================= +//------------------------------------------------------------------------- +template <class BASE> +inline SvXMLImportContext* OContainerImport< BASE >::CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList) +{ + // maybe it's a sub control + if (_rLocalName == m_sWrapperElementName) + { + if (m_xMeAsContainer.is()) + return implCreateControlWrapper(_nPrefix, _rLocalName); + else + { + OSL_ENSURE(sal_False, "OContainerImport::CreateChildContext: don't have an element!"); + return NULL; + } + } + + return BASE::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); +} + +//------------------------------------------------------------------------- +template <class BASE> +inline ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + OContainerImport< BASE >::createElement() +{ + // let the base class create the object + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xReturn = BASE::createElement(); + if (!xReturn.is()) + return xReturn; + + // ensure that the object is a XNameContainer (we strongly need this for inserting child elements) + m_xMeAsContainer = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >(xReturn, ::com::sun::star::uno::UNO_QUERY); + if (!m_xMeAsContainer.is()) + { + OSL_ENSURE(sal_False, "OContainerImport::createElement: invalid element (no XNameContainer) created!"); + xReturn.clear(); + } + + return xReturn; +} + +//------------------------------------------------------------------------- +template <class BASE> +inline void OContainerImport< BASE >::EndElement() +{ + BASE::EndElement(); + + // now that we have all children, attach the events + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xIndexContainer(m_xMeAsContainer, ::com::sun::star::uno::UNO_QUERY); + if (xIndexContainer.is()) + ODefaultEventAttacherManager::setEvents(xIndexContainer); +} + +//========================================================================= +//= OColumnImport +//========================================================================= +//------------------------------------------------------------------------- +template <class BASE> +OColumnImport< BASE >::OColumnImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxParentContainer, + OControlElement::ElementType _eType) + :BASE(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) + ,m_xColumnFactory(_rxParentContainer, ::com::sun::star::uno::UNO_QUERY) +{ + OSL_ENSURE(m_xColumnFactory.is(), "OColumnImport::OColumnImport: invalid parent container (no factory)!"); +} + +//------------------------------------------------------------------------- +// OElementImport overridables +template <class BASE> +::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > OColumnImport< BASE >::createElement() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xReturn; + // no call to the base class' method. We have to use the grid column factory + if (m_xColumnFactory.is()) + { + // create the column + xReturn = m_xColumnFactory->createColumn(this->m_sServiceName); + OSL_ENSURE(xReturn.is(), "OColumnImport::createElement: the factory returned an invalid object!"); + } + return xReturn; +} + diff --git a/xmloff/source/forms/eventexport.cxx b/xmloff/source/forms/eventexport.cxx new file mode 100644 index 000000000000..10ac91cd5c1f --- /dev/null +++ b/xmloff/source/forms/eventexport.cxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "eventexport.hxx" +#include <osl/diagnose.h> +#include "strings.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::script; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + + //===================================================================== + //= OEventDescriptorMapper + //===================================================================== + //--------------------------------------------------------------------- + OEventDescriptorMapper::OEventDescriptorMapper(const Sequence< ScriptEventDescriptor >& _rEvents) + { + sal_Int32 nEvents = _rEvents.getLength(); + + // translate the events + const ScriptEventDescriptor* pEvents = _rEvents.getConstArray(); + ::rtl::OUString sName; + ::rtl::OUString sLibrary, sLocalMacroName; + for (sal_Int32 i=0; i<nEvents; ++i, ++pEvents) + { + // the name of the event is build from listener interface and listener method name + sName = pEvents->ListenerType; + sName += EVENT_NAME_SEPARATOR; + sName += pEvents->EventMethod; + + Sequence< PropertyValue >& rMappedEvent = m_aMappedEvents[sName]; + + sLocalMacroName = pEvents->ScriptCode; + sLibrary = ::rtl::OUString(); + if ( 0 == pEvents->ScriptType.compareToAscii( EVENT_STARBASIC ) ) + { // for StarBasic, the library name is part of the ScriptCode + sal_Int32 nPrefixLen = sLocalMacroName.indexOf( ':' ); + DBG_ASSERT( 0 <= nPrefixLen, "OEventDescriptorMapper::OEventDescriptorMapper: invalid script code prefix!" ); + if ( 0 <= nPrefixLen ) + { + // the export handler for StarBasic expects "StarOffice", not "application" for application modules ... + sLibrary = sLocalMacroName.copy( 0, nPrefixLen ); + if ( sLibrary.equalsAscii( EVENT_APPLICATION ) ) + sLibrary = EVENT_STAROFFICE; + + sLocalMacroName = sLocalMacroName.copy( nPrefixLen + 1 ); + } + // tree property values to describe one event ... + rMappedEvent.realloc( sLibrary.getLength() ? 3 : 2 ); + + // ... the type + rMappedEvent[0] = PropertyValue(EVENT_TYPE, -1, makeAny(pEvents->ScriptType), PropertyState_DIRECT_VALUE); + + // and the macro name + rMappedEvent[1] = PropertyValue(EVENT_LOCALMACRONAME, -1, makeAny(sLocalMacroName), PropertyState_DIRECT_VALUE); + + // the library + if ( sLibrary.getLength() ) + rMappedEvent[2] = PropertyValue(EVENT_LIBRARY, -1, makeAny(sLibrary), PropertyState_DIRECT_VALUE); + } + else + { + rMappedEvent.realloc( 2 ); + rMappedEvent[0] = PropertyValue(EVENT_TYPE, -1, makeAny(pEvents->ScriptType), PropertyState_DIRECT_VALUE); + // and the macro name + rMappedEvent[1] = PropertyValue(EVENT_SCRIPTURL, -1, makeAny(pEvents->ScriptCode), PropertyState_DIRECT_VALUE); + } + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEventDescriptorMapper::replaceByName( const ::rtl::OUString&, const Any& ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) + { + throw IllegalArgumentException( + ::rtl::OUString::createFromAscii("replacing is not implemented for this wrapper class."), static_cast< ::cppu::OWeakObject* >(this), 1); + } + + //--------------------------------------------------------------------- + Any SAL_CALL OEventDescriptorMapper::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) + { + ConstMapString2PropertyValueSequenceIterator aPos = m_aMappedEvents.find(_rName); + if (m_aMappedEvents.end() == aPos) + throw NoSuchElementException( + ::rtl::OUString::createFromAscii("There is no element named ") += _rName, + static_cast< ::cppu::OWeakObject* >(this)); + + return makeAny(aPos->second); + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OEventDescriptorMapper::getElementNames( ) throw(RuntimeException) + { + Sequence< ::rtl::OUString > aReturn(m_aMappedEvents.size()); + ::rtl::OUString* pReturn = aReturn.getArray(); + for ( ConstMapString2PropertyValueSequenceIterator aCollect = m_aMappedEvents.begin(); + aCollect != m_aMappedEvents.end(); + ++aCollect, ++pReturn + ) + *pReturn = aCollect->first; + + return aReturn; + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OEventDescriptorMapper::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException) + { + ConstMapString2PropertyValueSequenceIterator aPos = m_aMappedEvents.find(_rName); + return m_aMappedEvents.end() != aPos; + } + + //--------------------------------------------------------------------- + Type SAL_CALL OEventDescriptorMapper::getElementType( ) throw(RuntimeException) + { + return ::getCppuType(static_cast< PropertyValue* >(NULL)); + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OEventDescriptorMapper::hasElements( ) throw(RuntimeException) + { + return !m_aMappedEvents.empty(); + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/eventexport.hxx b/xmloff/source/forms/eventexport.hxx new file mode 100644 index 000000000000..c20677e36f1a --- /dev/null +++ b/xmloff/source/forms/eventexport.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_EVENTEXPORT_HXX_ +#define _XMLOFF_FORMS_EVENTEXPORT_HXX_ + +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/stl_types.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OEventDescriptorMapper + //===================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace + > OEventDescriptorMapper_Base; + /** helper class wrapping different script event representations + + <p>In the form layer, the script events are represented by <type scope="com.sun.star.script">ScriptEventDescriptor</type> + instances. The office applications, on the other hand, represent their a single script event as sequence + of <type scope="com.sun.star.beans">PropertyValue</type>s, where all events of a given object are + accessible through a <type scope="com.sun.star.container">XNameReplace</type> interface.</p> + <p>This class maps the first representation of events of a single object to the second one.</p> + <p>This way, we can use the helper classes here in the project.</p> + */ + class OEventDescriptorMapper : public OEventDescriptorMapper_Base + { + protected: + DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >, MapString2PropertyValueSequence ); + MapString2PropertyValueSequence m_aMappedEvents; + + public: + OEventDescriptorMapper( + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents); + + // XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw(::com::sun::star::uno::RuntimeException); + }; + + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_EVENTEXPORT_HXX_ + diff --git a/xmloff/source/forms/eventimport.cxx b/xmloff/source/forms/eventimport.cxx new file mode 100644 index 000000000000..a16c7dd3e2c0 --- /dev/null +++ b/xmloff/source/forms/eventimport.cxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "eventimport.hxx" +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/extract.hxx> +#include "strings.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::script; + using namespace ::com::sun::star::container; + + //===================================================================== + //= OFormEventsImportContext + //===================================================================== + //--------------------------------------------------------------------- + OFormEventsImportContext::OFormEventsImportContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, IEventAttacher& _rEventAttacher) + :XMLEventsImportContext(_rImport, _nPrefix, _rLocalName) + ,m_rEventAttacher(_rEventAttacher) + { + } + + //--------------------------------------------------------------------- + void OFormEventsImportContext::EndElement() + { + Sequence< ScriptEventDescriptor > aTranslated(aCollectEvents.size()); + ScriptEventDescriptor* pTranslated = aTranslated.getArray(); + + // loop through the collected events and translate them + const PropertyValue* pEventDescription; + const PropertyValue* pEventDescriptionEnd; + sal_Int32 nSeparatorPos = -1; + for ( EventsVector::const_iterator aEvent = aCollectEvents.begin(); + aEvent != aCollectEvents.end(); + ++aEvent, ++pTranslated + ) + { + // the name of the event is built from ListenerType::EventMethod + nSeparatorPos = aEvent->first.indexOf(EVENT_NAME_SEPARATOR); + OSL_ENSURE(-1 != nSeparatorPos, "OFormEventsImportContext::EndElement: invalid (unrecognized) event name!"); + pTranslated->ListenerType = aEvent->first.copy(0, nSeparatorPos); + pTranslated->EventMethod = aEvent->first.copy(nSeparatorPos + EVENT_NAME_SEPARATOR.length); + + ::rtl::OUString sLibrary; + + // the local macro name and the event type are specified as properties + pEventDescription = aEvent->second.getConstArray(); + pEventDescriptionEnd = pEventDescription + aEvent->second.getLength(); + for (;pEventDescription != pEventDescriptionEnd; ++pEventDescription) + { + if ((0 == pEventDescription->Name.compareToAscii(EVENT_LOCALMACRONAME)) || + (0 == pEventDescription->Name.compareToAscii(EVENT_SCRIPTURL))) + pEventDescription->Value >>= pTranslated->ScriptCode; + else if (0 == pEventDescription->Name.compareToAscii(EVENT_TYPE)) + pEventDescription->Value >>= pTranslated->ScriptType; + else if ( 0 == pEventDescription->Name.compareToAscii( EVENT_LIBRARY ) ) + pEventDescription->Value >>= sLibrary; + } + + if ( 0 == pTranslated->ScriptType.compareToAscii( EVENT_STARBASIC ) ) + { + if ( 0 == sLibrary.compareToAscii( EVENT_STAROFFICE ) ) + sLibrary = EVENT_APPLICATION; + + if ( sLibrary.getLength() ) + { + // for StarBasic, the library is prepended + sal_Unicode cLibSeparator = ':'; + sLibrary += ::rtl::OUString( &cLibSeparator, 1 ); + } + sLibrary += pTranslated->ScriptCode; + pTranslated->ScriptCode = sLibrary; + } + } + + // register the events + m_rEventAttacher.registerEvents(aTranslated); + + XMLEventsImportContext::EndElement(); + } + + //===================================================================== + //= ODefaultEventAttacherManager + //===================================================================== + + ODefaultEventAttacherManager::~ODefaultEventAttacherManager() + { + } + + //------------------------------------------------------------------------- + void ODefaultEventAttacherManager::registerEvents(const Reference< XPropertySet >& _rxElement, + const Sequence< ScriptEventDescriptor >& _rEvents) + { + OSL_ENSURE(m_aEvents.end() == m_aEvents.find(_rxElement), + "ODefaultEventAttacherManager::registerEvents: already have events for this object!"); + // for the moment, only remember the script events + m_aEvents[_rxElement] = _rEvents; + } + + //------------------------------------------------------------------------- + void ODefaultEventAttacherManager::setEvents(const Reference< XIndexAccess >& _rxContainer) + { + Reference< XEventAttacherManager > xEventManager(_rxContainer, UNO_QUERY); + if (!xEventManager.is()) + { + OSL_ENSURE(sal_False, "ODefaultEventAttacherManager::setEvents: invalid argument!"); + return; + } + + // loop through all elements + sal_Int32 nCount = _rxContainer->getCount(); + Reference< XPropertySet > xCurrent; + ConstMapPropertySet2ScriptSequenceIterator aRegisteredEventsPos; + for (sal_Int32 i=0; i<nCount; ++i) + { + ::cppu::extractInterface(xCurrent, _rxContainer->getByIndex(i)); + if (xCurrent.is()) + { + aRegisteredEventsPos = m_aEvents.find(xCurrent); + if (m_aEvents.end() != aRegisteredEventsPos) + xEventManager->registerScriptEvents(i, aRegisteredEventsPos->second); + } + } + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/eventimport.hxx b/xmloff/source/forms/eventimport.hxx new file mode 100644 index 000000000000..9ea2d6fefc1d --- /dev/null +++ b/xmloff/source/forms/eventimport.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_EVENTIMPORT_HXX_ +#define _XMLOFF_FORMS_EVENTIMPORT_HXX_ + +#include <xmloff/XMLEventsImportContext.hxx> +#include "callbacks.hxx" +#include "ifacecompare.hxx" +#include <com/sun/star/container/XIndexAccess.hpp> + +class SvXMLImport; +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OFormEventsImportContext + //===================================================================== + class OFormEventsImportContext : public XMLEventsImportContext + { + protected: + IEventAttacher& m_rEventAttacher; + + public: + OFormEventsImportContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + IEventAttacher& _rEventAttacher); + + protected: + virtual void EndElement(); + }; + + //===================================================================== + //= ODefaultEventAttacherManager + //===================================================================== + class ODefaultEventAttacherManager : public IEventAttacherManager + { + protected: + DECLARE_STL_MAP( + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >, // map from + ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >, // map to + OPropertySetCompare, // compare method + MapPropertySet2ScriptSequence); // class name + // usually an event attacher manager will need to collect all script events registered, 'cause + // the _real_ XEventAttacherManager handles it's events by index, but out indicies are not fixed + // until _all_ controls have been inserted. + + MapPropertySet2ScriptSequence m_aEvents; + + public: + // IEventAttacherManager + virtual void registerEvents( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxElement, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ); + + protected: + void setEvents( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& _rxContainer + ); + + virtual ~ODefaultEventAttacherManager(); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_EVENTIMPORT_HXX_ + diff --git a/xmloff/source/forms/formattributes.cxx b/xmloff/source/forms/formattributes.cxx new file mode 100644 index 000000000000..fbe388a6a81a --- /dev/null +++ b/xmloff/source/forms/formattributes.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "formattributes.hxx" +#include "xmlnmspe.hxx" +#include <xmloff/xmluconv.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + + + //===================================================================== + //= OAttributeMetaData + //===================================================================== + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getCommonControlAttributeName(sal_Int32 _nId) + { + switch (_nId) + { + case CCA_NAME: return "name"; + case CCA_SERVICE_NAME: return "control-implementation"; + case CCA_BUTTON_TYPE: return "button-type"; + case CCA_CONTROL_ID: return "id"; + case CCA_CURRENT_SELECTED: return "current-selected"; + case CCA_CURRENT_VALUE: return "current-value"; + case CCA_DISABLED: return "disabled"; + case CCA_ENABLEVISIBLE: return "visible"; + case CCA_DROPDOWN: return "dropdown"; + case CCA_FOR: return "for"; + case CCA_IMAGE_DATA: return "image-data"; + case CCA_LABEL: return "label"; + case CCA_MAX_LENGTH: return "max-length"; + case CCA_PRINTABLE: return "printable"; + case CCA_READONLY: return "readonly"; + case CCA_SELECTED: return "selected"; + case CCA_SIZE: return "size"; + case CCA_TAB_INDEX: return "tab-index"; + case CCA_TARGET_FRAME: return "target-frame"; + case CCA_TARGET_LOCATION: return "href"; // the only special thing here: TargetLocation is represented by an xlink:href attribute + case CCA_TAB_STOP: return "tab-stop"; + case CCA_TITLE: return "title"; + case CCA_VALUE: return "value"; + case CCA_ORIENTATION: return "orientation"; + case CCA_VISUAL_EFFECT: return "visual-effect"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getCommonControlAttributeName: invalid id (maybe you or-ed two flags?)!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getCommonControlAttributeNamespace(sal_Int32 _nId) + { + if (CCA_TARGET_LOCATION == _nId) + return XML_NAMESPACE_XLINK; + + if (CCA_TARGET_FRAME == _nId) + return XML_NAMESPACE_OFFICE; + + return XML_NAMESPACE_FORM; + } + + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getFormAttributeName(FormAttributes _eAttrib) + { + switch (_eAttrib) + { + case faName: return "name"; + case faServiceName: return "service-name"; + case faAction: return "href"; // the only special thing here: Action is represented by an xlink:href attribute + case faEnctype: return "enctype"; + case faMethod: return "method"; + case faTargetFrame: return "target-frame"; + case faAllowDeletes: return "allow-deletes"; + case faAllowInserts: return "allow-inserts"; + case faAllowUpdates: return "allow-updates"; + case faApplyFilter: return "apply-filter"; + case faCommand: return "command"; + case faCommandType: return "command-type"; + case faEscapeProcessing: return "escape-processing"; + case faDatasource: return "datasource"; + case faConnectionResource: return "connection-resource"; + case faDetailFiels: return "detail-fields"; + case faFilter: return "filter"; + case faIgnoreResult: return "ignore-result"; + case faMasterFields: return "master-fields"; + case faNavigationMode: return "navigation-mode"; + case faOrder: return "order"; + case faTabbingCycle: return "tab-cycle"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getFormAttributeName: invalid id!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getFormAttributeNamespace(FormAttributes _eAttrib) + { + if (faAction == _eAttrib) + return XML_NAMESPACE_XLINK; + + if (faTargetFrame == _eAttrib) + return XML_NAMESPACE_OFFICE; + + return XML_NAMESPACE_FORM; + } + + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getDatabaseAttributeName(sal_Int32 _nId) + { + switch (_nId) + { + case DA_BOUND_COLUMN: return "bound-column"; + case DA_CONVERT_EMPTY: return "convert-empty-to-null"; + case DA_DATA_FIELD: return "data-field"; + case DA_LIST_SOURCE: return "list-source"; + case DA_LIST_SOURCE_TYPE: return "list-source-type"; + case DA_INPUT_REQUIRED: return "input-required"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getDatabaseAttributeName: invalid id (maybe you or-ed two flags?)!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getDatabaseAttributeNamespace(sal_Int32 /*_nId*/) + { + // nothing special here + return XML_NAMESPACE_FORM; + } + + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getBindingAttributeName(sal_Int32 _nId) + { + switch (_nId) + { + case BA_LINKED_CELL: return "linked-cell"; + case BA_LIST_LINKING_TYPE: return "list-linkage-type"; + case BA_LIST_CELL_RANGE: return "source-cell-range"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getBindingAttributeName: invalid id (maybe you or-ed two flags?)!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getBindingAttributeNamespace(sal_Int32) + { + // nothing special here + return XML_NAMESPACE_FORM; + } + + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getSpecialAttributeName(sal_Int32 _nId) + { + switch (_nId) + { + case SCA_ECHO_CHAR: return "echo-char"; + case SCA_MAX_VALUE: return "max-value"; + case SCA_MIN_VALUE: return "min-value"; + case SCA_VALIDATION: return "validation"; + case SCA_MULTI_LINE: return "multi-line"; + case SCA_AUTOMATIC_COMPLETION: return "auto-complete"; + case SCA_MULTIPLE: return "multiple"; + case SCA_DEFAULT_BUTTON: return "default-button"; + case SCA_CURRENT_STATE: return "current-state"; + case SCA_IS_TRISTATE: return "is-tristate"; + case SCA_STATE: return "state"; + case SCA_COLUMN_STYLE_NAME: return "text-style-name"; + case SCA_STEP_SIZE: return "step-size"; + case SCA_PAGE_STEP_SIZE: return "page-step-size"; + case SCA_REPEAT_DELAY: return "delay-for-repeat"; + case SCA_TOGGLE: return "toggle"; + case SCA_FOCUS_ON_CLICK: return "focus-on-click"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getSpecialAttributeName: invalid id (maybe you or-ed two flags?)!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getSpecialAttributeNamespace(sal_Int32 /*_nId*/) + { + // nothing special here + return XML_NAMESPACE_FORM; + } + + //--------------------------------------------------------------------- + const sal_Char* OAttributeMetaData::getOfficeFormsAttributeName(OfficeFormsAttributes _eAttrib) + { + switch (_eAttrib) + { + case ofaAutomaticFocus: return "automatic-focus"; + case ofaApplyDesignMode: return "apply-design-mode"; + default: + OSL_ENSURE(sal_False, "OAttributeMetaData::getOfficeFormsAttributeName: invalid id!"); + } + return ""; + } + + //--------------------------------------------------------------------- + sal_uInt16 OAttributeMetaData::getOfficeFormsAttributeNamespace(OfficeFormsAttributes /* _eAttrib */) + { + // nothing special here + return XML_NAMESPACE_FORM; + } + + //===================================================================== + //= OAttribute2Property + //===================================================================== + //--------------------------------------------------------------------- + OAttribute2Property::OAttribute2Property() + { + } + + //--------------------------------------------------------------------- + OAttribute2Property::~OAttribute2Property() + { + } + + //--------------------------------------------------------------------- + const OAttribute2Property::AttributeAssignment* OAttribute2Property::getAttributeTranslation( + const ::rtl::OUString& _rAttribName) + { + ConstAttributeAssignmentsIterator aPos = m_aKnownProperties.find(_rAttribName); + if (m_aKnownProperties.end() != aPos) + return &aPos->second; + return NULL; + } + + //--------------------------------------------------------------------- + void OAttribute2Property::addStringProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Char* _pAttributeDefault) + { + implAdd(_pAttributeName, _rPropertyName, ::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), + _pAttributeDefault ? ::rtl::OUString::createFromAscii(_pAttributeDefault) : ::rtl::OUString()); + } + + //--------------------------------------------------------------------- + void OAttribute2Property::addBooleanProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Bool _bAttributeDefault, const sal_Bool _bInverseSemantics) + { + ::rtl::OUStringBuffer aDefault; + SvXMLUnitConverter::convertBool(aDefault, _bAttributeDefault); + AttributeAssignment& aAssignment = implAdd(_pAttributeName, _rPropertyName, ::getBooleanCppuType(), aDefault.makeStringAndClear()); + aAssignment.bInverseSemantics = _bInverseSemantics; + } + + //--------------------------------------------------------------------- + void OAttribute2Property::addInt16Property( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Int16 _nAttributeDefault) + { + ::rtl::OUStringBuffer aDefault; + SvXMLUnitConverter::convertNumber(aDefault, (sal_Int32)_nAttributeDefault); + implAdd(_pAttributeName, _rPropertyName, ::getCppuType( static_cast< sal_Int16* >(NULL) ), aDefault.makeStringAndClear()); + } + + //--------------------------------------------------------------------- + void OAttribute2Property::addInt32Property( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Int32 _nAttributeDefault) + { + ::rtl::OUStringBuffer aDefault; + SvXMLUnitConverter::convertNumber( aDefault, _nAttributeDefault ); + implAdd( _pAttributeName, _rPropertyName, ::getCppuType( static_cast< sal_Int32* >(NULL) ), aDefault.makeStringAndClear() ); + } + + //--------------------------------------------------------------------- + void OAttribute2Property::addEnumProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_uInt16 _nAttributeDefault, const SvXMLEnumMapEntry* _pValueMap, + const ::com::sun::star::uno::Type* _pType) + { + ::rtl::OUStringBuffer aDefault; + SvXMLUnitConverter::convertEnum(aDefault, _nAttributeDefault, _pValueMap); + AttributeAssignment& aAssignment = implAdd(_pAttributeName, _rPropertyName, + _pType ? *_pType : ::getCppuType( static_cast< sal_Int32* >(NULL) ), + // this assumes that the setPropertyValue for enums can handle int32's .... + aDefault.makeStringAndClear()); + aAssignment.pEnumMap = _pValueMap; + } + + //--------------------------------------------------------------------- + OAttribute2Property::AttributeAssignment& OAttribute2Property::implAdd( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const ::com::sun::star::uno::Type& _rType, const ::rtl::OUString& /*_rDefaultString*/) + { + OSL_ENSURE(m_aKnownProperties.end() == m_aKnownProperties.find(::rtl::OUString::createFromAscii(_pAttributeName)), + "OAttribute2Property::implAdd: already have this attribute!"); + + ::rtl::OUString sAttributeName = ::rtl::OUString::createFromAscii(_pAttributeName); + + AttributeAssignment aAssignment; + aAssignment.sAttributeName = sAttributeName; + aAssignment.sPropertyName = _rPropertyName; + aAssignment.aPropertyType = _rType; + + // redundance, the accessor is stored in aAssignment.sAttributeName, too + return m_aKnownProperties[sAttributeName] = aAssignment; + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/formattributes.hxx b/xmloff/source/forms/formattributes.hxx new file mode 100644 index 000000000000..121476a9b21c --- /dev/null +++ b/xmloff/source/forms/formattributes.hxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMATTRIBUTES_HXX_ +#define _XMLOFF_FORMATTRIBUTES_HXX_ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <sal/types.h> +#include <vos/refernce.hxx> +#include <comphelper/stl_types.hxx> + +class SvXMLExport; +struct SvXMLEnumMapEntry; + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + // flags for common control attributes + #define CCA_NAME 0x00000001 + #define CCA_SERVICE_NAME 0x00000002 + #define CCA_BUTTON_TYPE 0x00000004 + #define CCA_CONTROL_ID 0x00000008 + #define CCA_CURRENT_SELECTED 0x00000010 + #define CCA_CURRENT_VALUE 0x00000020 + #define CCA_DISABLED 0x00000040 + #define CCA_DROPDOWN 0x00000080 + #define CCA_FOR 0x00000100 + #define CCA_IMAGE_DATA 0x00000200 + #define CCA_LABEL 0x00000400 + #define CCA_MAX_LENGTH 0x00000800 + #define CCA_PRINTABLE 0x00001000 + #define CCA_READONLY 0x00002000 + #define CCA_SELECTED 0x00004000 + #define CCA_SIZE 0x00008000 + #define CCA_TAB_INDEX 0x00010000 + #define CCA_TARGET_FRAME 0x00020000 + #define CCA_TARGET_LOCATION 0x00040000 + #define CCA_TAB_STOP 0x00080000 + #define CCA_TITLE 0x00100000 + #define CCA_VALUE 0x00200000 + #define CCA_ORIENTATION 0x00400000 + #define CCA_VISUAL_EFFECT 0x00800000 + #define CCA_ENABLEVISIBLE 0x01000000 + + // flags for database control atttributes + #define DA_BOUND_COLUMN 0x00000001 + #define DA_CONVERT_EMPTY 0x00000002 + #define DA_DATA_FIELD 0x00000004 + #define DA_LIST_SOURCE 0x00000008 + #define DA_LIST_SOURCE_TYPE 0x00000010 + #define DA_INPUT_REQUIRED 0x00000020 + + // flags for binding related control attributes + #define BA_LINKED_CELL 0x00000001 + #define BA_LIST_LINKING_TYPE 0x00000002 + #define BA_LIST_CELL_RANGE 0x00000004 + #define BA_XFORMS_BIND 0x00000008 + #define BA_XFORMS_LISTBIND 0x00000010 + #define BA_XFORMS_SUBMISSION 0x00000020 + + // flags for event attributes + #define EA_CONTROL_EVENTS 0x00000001 + #define EA_ON_CHANGE 0x00000002 + #define EA_ON_CLICK 0x00000004 + #define EA_ON_DBLCLICK 0x00000008 + #define EA_ON_SELECT 0x00000010 + + /// attributes in the xml tag representing a form + enum FormAttributes + { + faName, + faServiceName, + faAction, + faEnctype, + faMethod, + faTargetFrame, + faAllowDeletes, + faAllowInserts, + faAllowUpdates, + faApplyFilter, + faCommand, + faCommandType, + faEscapeProcessing, + faDatasource, + faConnectionResource, + faDetailFiels, + faFilter, + faIgnoreResult, + faMasterFields, + faNavigationMode, + faOrder, + faTabbingCycle + }; + + // any other attributes, which are special to some control types + #define SCA_ECHO_CHAR 0x00000001 + #define SCA_MAX_VALUE 0x00000002 + #define SCA_MIN_VALUE 0x00000004 + #define SCA_VALIDATION 0x00000008 + #define SCA_MULTI_LINE 0x00000020 + #define SCA_AUTOMATIC_COMPLETION 0x00000080 + #define SCA_MULTIPLE 0x00000100 + #define SCA_DEFAULT_BUTTON 0x00000200 + #define SCA_CURRENT_STATE 0x00000400 + #define SCA_IS_TRISTATE 0x00000800 + #define SCA_STATE 0x00001000 + #define SCA_COLUMN_STYLE_NAME 0x00002000 + #define SCA_STEP_SIZE 0x00004000 + #define SCA_PAGE_STEP_SIZE 0x00008000 + #define SCA_REPEAT_DELAY 0x00010000 + #define SCA_TOGGLE 0x00020000 + #define SCA_FOCUS_ON_CLICK 0x00040000 + #define SCA_IMAGE_POSITION 0x00080000 + + // attributes of the office:forms element + enum OfficeFormsAttributes + { + ofaAutomaticFocus, + ofaApplyDesignMode + }; + + //===================================================================== + //= OAttributeMetaData + //===================================================================== + /** allows the translation of attribute ids into strings. + + <p>This class does not allow to connect xml attributes to property names or + something like that, it only deals with the xml side</p> + */ + class OAttributeMetaData + { + public: + /** calculates the xml attribute representation of a common control attribute. + @param _nId + the id of the attribute. Has to be one of the CCA_* constants. + */ + static const sal_Char* getCommonControlAttributeName(sal_Int32 _nId); + + /** calculates the xml namespace key to use for a common control attribute + @param _nId + the id of the attribute. Has to be one of the CCA_* constants. + */ + static sal_uInt16 getCommonControlAttributeNamespace(sal_Int32 _nId); + + /** retrieves the name of an attribute of a form xml representation + @param _eAttrib + enum value specifying the attribute + */ + static const sal_Char* getFormAttributeName(FormAttributes _eAttrib); + + /** calculates the xml namespace key to use for a attribute of a form xml representation + @param _eAttrib + enum value specifying the attribute + */ + static sal_uInt16 getFormAttributeNamespace(FormAttributes _eAttrib); + + /** calculates the xml attribute representation of a database attribute. + @param _nId + the id of the attribute. Has to be one of the DA_* constants. + */ + static const sal_Char* getDatabaseAttributeName(sal_Int32 _nId); + + /** calculates the xml namespace key to use for a database attribute. + @param _nId + the id of the attribute. Has to be one of the DA_* constants. + */ + static sal_uInt16 getDatabaseAttributeNamespace(sal_Int32 _nId); + + /** calculates the xml attribute representation of a special attribute. + @param _nId + the id of the attribute. Has to be one of the SCA_* constants. + */ + static const sal_Char* getSpecialAttributeName(sal_Int32 _nId); + + /** calculates the xml attribute representation of a binding attribute. + @param _nId + the id of the attribute. Has to be one of the BA_* constants. + */ + static const sal_Char* getBindingAttributeName(sal_Int32 _nId); + + /** calculates the xml namespace key to use for a binding attribute. + @param _nId + the id of the attribute. Has to be one of the BA_* constants. + */ + static sal_uInt16 getBindingAttributeNamespace(sal_Int32 _nId); + + /** calculates the xml namespace key to use for a special attribute. + @param _nId + the id of the attribute. Has to be one of the SCA_* constants. + */ + static sal_uInt16 getSpecialAttributeNamespace(sal_Int32 _nId); + + /** calculates the xml attribute representation of a attribute of the office:forms element + @param _nId + the id of the attribute + */ + static const sal_Char* getOfficeFormsAttributeName(OfficeFormsAttributes _eAttrib); + + /** calculates the xml namedspace key of a attribute of the office:forms element + @param _nId + the id of the attribute + */ + static sal_uInt16 getOfficeFormsAttributeNamespace(OfficeFormsAttributes _eAttrib); + }; + + //===================================================================== + //= OAttribute2Property + //===================================================================== + /** some kind of opposite to the OAttributeMetaData class. Able to translate + attributes into property names/types + + <p>The construction of this class is rather expensive (or at least it's initialization from outside), + so it should be shared</p> + */ + class OAttribute2Property + { + public: + // TODO: maybe the following struct should be used for exports, too. In this case we would not need to + // store it's instances in a map, but in a vector for faster access. + struct AttributeAssignment + { + ::rtl::OUString sAttributeName; // the attribute name + ::rtl::OUString sPropertyName; // the property name + ::com::sun::star::uno::Type aPropertyType; // the property type + ::rtl::OUString sAttributeDefault; // the default if the attribute is not present + + // entries which are special to some value types + const SvXMLEnumMapEntry* pEnumMap; // the enum map, if appliable + sal_Bool bInverseSemantics; // for booleanss: attribute and property value have the same or an inverse semantics? + + AttributeAssignment() : pEnumMap(NULL), bInverseSemantics(sal_False) { } + }; + + protected: + DECLARE_STL_USTRINGACCESS_MAP( AttributeAssignment, AttributeAssignments ); + AttributeAssignments m_aKnownProperties; + + public: + OAttribute2Property(); + virtual ~OAttribute2Property(); + + /** return the AttributeAssignment which corresponds to the given attribute + + @param _rAttribName + the name of the attrribute + @return + a pointer to the <type>AttributeAssignment</type> structure as requested, NULL if the attribute + does not represent a property. + */ + const AttributeAssignment* getAttributeTranslation( + const ::rtl::OUString& _rAttribName); + + /** add a attribute assignment referring to a string property to the map + @param _pAttributeName + the name of the attrribute + @param _rPropertyName + the name of the property assigned to the attribute + @param _pAttributeDefault + the default value for the attribute, if any. May be NULL, in this case the default is assumed to be + an empty string. + */ + void addStringProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Char* _pAttributeDefault = NULL); + + /** add a attribute assignment referring to a boolean property to the map + + @param _pAttributeName + the name of the attrribute + @param _rPropertyName + the name of the property assigned to the attribute + @param _bAttributeDefault + the default value for the attribute. + @param _bInverseSemantics + if <TRUE/>, a attribute value of <TRUE/> means a property value of <FALSE/> and vice verse.<br/> + if <FALSE/>, the attribute value is used as property value directly + */ + void addBooleanProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Bool _bAttributeDefault, const sal_Bool _bInverseSemantics = sal_False); + + /** add a attribute assignment referring to an int16 property to the map + + @param _pAttributeName + the name of the attrribute + @param _rPropertyName + the name of the property assigned to the attribute + @param _nAttributeDefault + the default value for the attribute. + */ + void addInt16Property( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Int16 _nAttributeDefault); + + /** add a attribute assignment referring to an int32 property to the map + + @param _pAttributeName + the name of the attrribute + @param _rPropertyName + the name of the property assigned to the attribute + @param _nAttributeDefault + the default value for the attribute. + */ + void addInt32Property( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_Int32 _nAttributeDefault ); + + /** add a attribute assignment referring to an enum property to the map + + @param _pAttributeName + the name of the attrribute + @param _rPropertyName + the name of the property assigned to the attribute + @param _nAttributeDefault + the default value for the attribute, as (32bit) integer + @param _pValueMap + the map to translate strings into enum values + @param _pType + the type of the property. May be NULL, in this case 32bit integer is assumed. + */ + void addEnumProperty( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const sal_uInt16 _nAttributeDefault, const SvXMLEnumMapEntry* _pValueMap, + const ::com::sun::star::uno::Type* _pType = NULL); + + protected: + /// some common code for the various add*Property methods + AttributeAssignment& implAdd( + const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, + const ::com::sun::star::uno::Type& _rType, const ::rtl::OUString& _rDefaultString); + }; +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMATTRIBUTES_HXX_ + diff --git a/xmloff/source/forms/formcellbinding.cxx b/xmloff/source/forms/formcellbinding.cxx new file mode 100644 index 000000000000..95284d61f630 --- /dev/null +++ b/xmloff/source/forms/formcellbinding.cxx @@ -0,0 +1,490 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "formcellbinding.hxx" +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/form/XGridColumnFactory.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include "strings.hxx" +#include <osl/diagnose.h> +#include <rtl/logfile.hxx> + +#include <functional> +#include <algorithm> + +//............................................................................ +namespace xmloff +{ +//............................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::sheet; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::drawing; + using namespace ::com::sun::star::table; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::form::binding; + +namespace +{ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::container::XChild; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::uno::UNO_QUERY; + + //.................................................................... + template< class TYPE > + Reference< TYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode ) + { + Reference< TYPE > xTypedNode( _rxModelNode, UNO_QUERY ); + if ( xTypedNode.is() ) + return xTypedNode; + else + { + Reference< XChild > xChild( _rxModelNode, UNO_QUERY ); + if ( xChild.is() ) + return getTypedModelNode< TYPE >( xChild->getParent() ); + else + return NULL; + } + } + + //.................................................................... + Reference< XModel > getDocument( const Reference< XInterface >& _rxModelNode ) + { + return getTypedModelNode< XModel >( _rxModelNode ); + } + + //.................................................................... + struct StringCompare : public ::std::unary_function< ::rtl::OUString, bool > + { + private: + const ::rtl::OUString m_sReference; + + public: + StringCompare( const ::rtl::OUString& _rReference ) : m_sReference( _rReference ) { } + + inline bool operator()( const ::rtl::OUString& _rCompare ) + { + return ( _rCompare == m_sReference ); + } + }; +} + +//======================================================================== +//= FormCellBindingHelper +//======================================================================== +//------------------------------------------------------------------------ +FormCellBindingHelper::FormCellBindingHelper( const Reference< XPropertySet >& _rxControlModel, const Reference< XModel >& _rxDocument ) + :m_xControlModel( _rxControlModel ) + ,m_xDocument( _rxDocument, UNO_QUERY ) +{ + OSL_ENSURE( m_xControlModel.is(), "FormCellBindingHelper::FormCellBindingHelper: invalid control model!" ); + + if ( !m_xDocument.is() ) + m_xDocument = m_xDocument.query( getDocument( m_xControlModel ) ); + OSL_ENSURE( m_xDocument.is(), "FormCellBindingHelper::FormCellBindingHelper: Did not find the spreadsheet document!" ); +} + +//------------------------------------------------------------------------ +sal_Bool FormCellBindingHelper::livesInSpreadsheetDocument( const Reference< XPropertySet >& _rxControlModel ) +{ + Reference< XSpreadsheetDocument > xDocument( getDocument( _rxControlModel ), UNO_QUERY ); + return xDocument.is(); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription, CellAddress& /* [out] */ _rAddress, sal_Int16 /*_nAssumeSheet*/ ) const +{ + Any aAddress; + return doConvertAddressRepresentations( + PROPERTY_FILE_REPRESENTATION, + makeAny( _rAddressDescription ), + PROPERTY_ADDRESS, + aAddress, + false + ) + && ( aAddress >>= _rAddress ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription, + CellRangeAddress& /* [out] */ _rAddress ) const +{ + Any aAddress; + return doConvertAddressRepresentations( + PROPERTY_FILE_REPRESENTATION, + makeAny( _rAddressDescription ), + PROPERTY_ADDRESS, + aAddress, + true + ) + && ( aAddress >>= _rAddress ); +} + +//------------------------------------------------------------------------ +Reference< XValueBinding > FormCellBindingHelper::createCellBindingFromStringAddress( const ::rtl::OUString& _rAddress, bool _bUseIntegerBinding ) const +{ + Reference< XValueBinding > xBinding; + if ( !m_xDocument.is() ) + // very bad ... + return xBinding; + + // get the UNO representation of the address + CellAddress aAddress; + if ( !_rAddress.getLength() || !convertStringAddress( _rAddress, aAddress ) ) + return xBinding; + + xBinding = xBinding.query( createDocumentDependentInstance( + _bUseIntegerBinding ? SERVICE_LISTINDEXCELLBINDING : SERVICE_CELLVALUEBINDING, + PROPERTY_BOUND_CELL, + makeAny( aAddress ) + ) ); + + return xBinding; +} + +//------------------------------------------------------------------------ +Reference< XListEntrySource > FormCellBindingHelper::createCellListSourceFromStringAddress( const ::rtl::OUString& _rAddress ) const +{ + Reference< XListEntrySource > xSource; + + CellRangeAddress aRangeAddress; + if ( !convertStringAddress( _rAddress, aRangeAddress ) ) + return xSource; + + // create a range object for this address + xSource = xSource.query( createDocumentDependentInstance( + SERVICE_CELLRANGELISTSOURCE, + PROPERTY_LIST_CELL_RANGE, + makeAny( aRangeAddress ) + ) ); + + return xSource; +} + +//------------------------------------------------------------------------ +::rtl::OUString FormCellBindingHelper::getStringAddressFromCellBinding( const Reference< XValueBinding >& _rxBinding ) const +{ + OSL_PRECOND( !_rxBinding.is() || isCellBinding( _rxBinding ), "FormCellBindingHelper::getStringAddressFromCellBinding: this is no cell binding!" ); + + ::rtl::OUString sAddress; + try + { + Reference< XPropertySet > xBindingProps( _rxBinding, UNO_QUERY ); + OSL_ENSURE( xBindingProps.is() || !_rxBinding.is(), "FormCellBindingHelper::getStringAddressFromCellBinding: no property set for the binding!" ); + if ( xBindingProps.is() ) + { + CellAddress aAddress; + xBindingProps->getPropertyValue( PROPERTY_BOUND_CELL ) >>= aAddress; + + Any aStringAddress; + doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aAddress ), + PROPERTY_FILE_REPRESENTATION, aStringAddress, false ); + + aStringAddress >>= sAddress; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormCellBindingHelper::getStringAddressFromCellBinding: caught an exception!" ); + } + + return sAddress; +} + +//------------------------------------------------------------------------ +::rtl::OUString FormCellBindingHelper::getStringAddressFromCellListSource( const Reference< XListEntrySource >& _rxSource ) const +{ + OSL_PRECOND( !_rxSource.is() || isCellRangeListSource( _rxSource ), "FormCellBindingHelper::getStringAddressFromCellListSource: this is no cell list source!" ); + + ::rtl::OUString sAddress; + try + { + Reference< XPropertySet > xSourceProps( _rxSource, UNO_QUERY ); + OSL_ENSURE( xSourceProps.is() || !_rxSource.is(), "FormCellBindingHelper::getStringAddressFromCellListSource: no property set for the list source!" ); + if ( xSourceProps.is() ) + { + CellRangeAddress aRangeAddress; + xSourceProps->getPropertyValue( PROPERTY_LIST_CELL_RANGE ) >>= aRangeAddress; + + Any aStringAddress; + doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aRangeAddress ), + PROPERTY_FILE_REPRESENTATION, aStringAddress, true ); + aStringAddress >>= sAddress; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormCellBindingHelper::getStringAddressFromCellListSource: caught an exception!" ); + } + + return sAddress; +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const Reference< XSpreadsheetDocument >& _rxDocument, const ::rtl::OUString& _rService ) SAL_THROW(()) +{ + bool bYesItIs = false; + + try + { + Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY ); + if ( xSI.is() && xSI->supportsService( SERVICE_SPREADSHEET_DOCUMENT ) ) + { + Reference< XMultiServiceFactory > xDocumentFactory( _rxDocument, UNO_QUERY ); + OSL_ENSURE( xDocumentFactory.is(), "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: spreadsheet document, but no factory?" ); + + Sequence< ::rtl::OUString > aAvailableServices; + if ( xDocumentFactory.is() ) + aAvailableServices = xDocumentFactory->getAvailableServiceNames( ); + + const ::rtl::OUString* pFound = ::std::find_if( + aAvailableServices.getConstArray(), + aAvailableServices.getConstArray() + aAvailableServices.getLength(), + StringCompare( _rService ) + ); + if ( pFound - aAvailableServices.getConstArray() < aAvailableServices.getLength() ) + { + bYesItIs = true; + } + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: caught an exception!" ); + } + + return bYesItIs; +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const ::rtl::OUString& _rService ) const SAL_THROW(()) +{ + return isSpreadsheetDocumentWhichSupplies( m_xDocument, _rService ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isListCellRangeAllowed( const Reference< XModel >& _rxDocument ) +{ + return isSpreadsheetDocumentWhichSupplies( + Reference< XSpreadsheetDocument >( _rxDocument, UNO_QUERY ), + SERVICE_CELLRANGELISTSOURCE + ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isListCellRangeAllowed( ) const +{ + bool bAllow( false ); + + Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); + if ( xSink.is() ) + { + bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_CELLRANGELISTSOURCE ); + } + + return bAllow; +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isCellBindingAllowed( ) const +{ + bool bAllow( false ); + + Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); + if ( xBindable.is() ) + { + // the control can potentially be bound to an external value + // Does it live within a Calc document, and is able to supply CellBindings? + bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_CELLVALUEBINDING ); + } + + return bAllow; +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isCellBindingAllowed( const Reference< XModel >& _rxDocument ) +{ + return isSpreadsheetDocumentWhichSupplies( + Reference< XSpreadsheetDocument >( _rxDocument, UNO_QUERY ), + SERVICE_CELLVALUEBINDING + ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isCellBinding( const Reference< XValueBinding >& _rxBinding ) const +{ + return doesComponentSupport( _rxBinding.get(), SERVICE_CELLVALUEBINDING ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isCellIntegerBinding( const Reference< XValueBinding >& _rxBinding ) const +{ + return doesComponentSupport( _rxBinding.get(), SERVICE_LISTINDEXCELLBINDING ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::isCellRangeListSource( const Reference< XListEntrySource >& _rxSource ) const +{ + return doesComponentSupport( _rxSource.get(), SERVICE_CELLRANGELISTSOURCE ); +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::doesComponentSupport( const Reference< XInterface >& _rxComponent, const ::rtl::OUString& _rService ) const +{ + bool bDoes = false; + Reference< XServiceInfo > xSI( _rxComponent, UNO_QUERY ); + bDoes = xSI.is() && xSI->supportsService( _rService ); + return bDoes; +} + +//------------------------------------------------------------------------ +Reference< XValueBinding > FormCellBindingHelper::getCurrentBinding( ) const +{ + Reference< XValueBinding > xBinding; + Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); + if ( xBindable.is() ) + xBinding = xBindable->getValueBinding(); + return xBinding; +} + +//------------------------------------------------------------------------ +Reference< XListEntrySource > FormCellBindingHelper::getCurrentListSource( ) const +{ + Reference< XListEntrySource > xSource; + Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); + if ( xSink.is() ) + xSource = xSink->getListEntrySource(); + return xSource; +} + +//------------------------------------------------------------------------ +void FormCellBindingHelper::setBinding( const Reference< XValueBinding >& _rxBinding ) +{ + Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); + OSL_PRECOND( xBindable.is(), "FormCellBindingHelper::setBinding: the object is not bindable!" ); + if ( xBindable.is() ) + xBindable->setValueBinding( _rxBinding ); +} + +//------------------------------------------------------------------------ +void FormCellBindingHelper::setListSource( const Reference< XListEntrySource >& _rxSource ) +{ + Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); + OSL_PRECOND( xSink.is(), "FormCellBindingHelper::setListSource: the object is no list entry sink!" ); + if ( xSink.is() ) + xSink->setListEntrySource( _rxSource ); +} + +//------------------------------------------------------------------------ +Reference< XInterface > FormCellBindingHelper::createDocumentDependentInstance( const ::rtl::OUString& _rService, const ::rtl::OUString& _rArgumentName, + const Any& _rArgumentValue ) const +{ + Reference< XInterface > xReturn; + + Reference< XMultiServiceFactory > xDocumentFactory( m_xDocument, UNO_QUERY ); + OSL_ENSURE( xDocumentFactory.is(), "FormCellBindingHelper::createDocumentDependentInstance: no document service factory!" ); + if ( xDocumentFactory.is() ) + { + try + { + if ( _rArgumentName.getLength() ) + { + NamedValue aArg; + aArg.Name = _rArgumentName; + aArg.Value = _rArgumentValue; + + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= aArg; + + xReturn = xDocumentFactory->createInstanceWithArguments( _rService, aArgs ); + } + else + { + xReturn = xDocumentFactory->createInstance( _rService ); + } + } + catch ( const Exception& ) + { + OSL_ENSURE( sal_False, "FormCellBindingHelper::createDocumentDependentInstance: could not create the binding at the document!" ); + } + } + return xReturn; +} + +//------------------------------------------------------------------------ +bool FormCellBindingHelper::doConvertAddressRepresentations( const ::rtl::OUString& _rInputProperty, const Any& _rInputValue, + const ::rtl::OUString& _rOutputProperty, Any& _rOutputValue, bool _bIsRange ) const SAL_THROW(()) +{ + bool bSuccess = false; + + Reference< XPropertySet > xConverter( + createDocumentDependentInstance( + _bIsRange ? SERVICE_RANGEADDRESS_CONVERSION : SERVICE_ADDRESS_CONVERSION, + ::rtl::OUString(), + Any() + ), + UNO_QUERY + ); + OSL_ENSURE( xConverter.is(), "FormCellBindingHelper::doConvertAddressRepresentations: could not get a converter service!" ); + if ( xConverter.is() ) + { + try + { + xConverter->setPropertyValue( _rInputProperty, _rInputValue ); + _rOutputValue = xConverter->getPropertyValue( _rOutputProperty ); + bSuccess = true; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormCellBindingHelper::doConvertAddressRepresentations: caught an exception!" ); + } + } + + return bSuccess; +} + +//............................................................................ +} // namespace xmloff +//............................................................................ diff --git a/xmloff/source/forms/formcellbinding.hxx b/xmloff/source/forms/formcellbinding.hxx new file mode 100644 index 000000000000..18df52ed2a4d --- /dev/null +++ b/xmloff/source/forms/formcellbinding.hxx @@ -0,0 +1,279 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef XMLOFF_FORMS_FORMCELLBINDING +#define XMLOFF_FORMS_FORMCELLBINDING + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include <com/sun/star/form/binding/XListEntrySource.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/frame/XModel.hpp> + +//............................................................................ +namespace xmloff +{ +//............................................................................ + + //======================================================================== + //= FormCellBindingHelper + //======================================================================== + /** encapsulates functionality related to binding a form control to a spreadsheet cell + */ + class FormCellBindingHelper + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xControlModel; // the model we work for + ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > + m_xDocument; // the document where the model lives + + public: + /** determines whether the given control model lives in a spreadsheet document + <p>If this method returns <FALSE/>, you cannot instantiate a CellBindingHelper with + this model, since then no of it's functionality will be available.</p> + */ + static sal_Bool livesInSpreadsheetDocument( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel + ); + + /** ctor + @param _rxControlModel + the control model which is or will be bound + @param _rxDocument + the document. If this is <NULL/>, the document will be obtained from the model + itself by walkong up the chain of its ancestors.<br/> + This parameter can be used if the control model is not (yet) part of a document + model. + */ + FormCellBindingHelper( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument + ); + + public: + /** gets a cell binding for the given address + @precond + isCellBindingAllowed returns <TRUE/> + */ + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + createCellBindingFromStringAddress( + const ::rtl::OUString& _rAddress, + bool _bUseIntegerBinding + ) const; + + /** gets a cell range list source binding for the given address + */ + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + createCellListSourceFromStringAddress( const ::rtl::OUString& _rAddress ) const; + + /** creates a string representation for the given value binding's address + + <p>If the sheet of the bound cell is the same as the sheet which our control belongs + to, then the sheet name is omitted in the resulting string representation.</p> + + @precond + The binding is a valid cell binding, or <NULL/> + @see isCellBinding + */ + ::rtl::OUString getStringAddressFromCellBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ) const; + + /** creates a string representation for the given list source's range address + + <p>If the sheet of the cell range which acts as list source is the same as the + sheet which our control belongs to, then the sheet name is omitted in the + resulting string representation.</p> + + @precond + The object is a valid cell range list source, or <NULL/> + @see isCellRangeListSource + */ + ::rtl::OUString getStringAddressFromCellListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + ) const; + + /** returns the current binding of our control model, if any. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + getCurrentBinding( ) const; + + /** returns the current external list source of the control model, if any + */ + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + getCurrentListSource( ) const; + + /** sets a new binding for our control model + @precond + the control model is bindable (which is implied by <member>isCellBindingAllowed</member> + returning <TRUE/>) + */ + void setBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ); + + /** sets a list source for our control model + @precond + the control model is a list sink (which is implied by <member>isListCellRangeAllowed</member> + returning <TRUE/>) + */ + void setListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + ); + + /** checks whether it's possible to bind the control model to a spreadsheet cell + */ + bool isCellBindingAllowed( ) const; + + /** checks whether within the given document, it's possible to bind control models to spreadsheet cells + */ + static bool isCellBindingAllowed( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument + ); + + /** checks whether it's possible to bind the control model to a range of spreadsheet cells + supplying the list entries + */ + bool isListCellRangeAllowed( ) const; + + /** checks whether within the given document, it's possible to bind the control model to a range of + spreadsheet cells supplying the list entries + */ + static bool isListCellRangeAllowed( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument + ); + + /** checks whether a given binding is a spreadsheet cell binding + */ + bool isCellBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ) const; + + /** checks whether a given binding is a spreadsheet cell binding, exchanging + integer values + */ + bool isCellIntegerBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ) const; + + /** checks whether a given list source is a spreadsheet cell list source + */ + bool isCellRangeListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + ) const; + + protected: + /** creates an address object from a string representation of a cell address + */ + bool convertStringAddress( + const ::rtl::OUString& _rAddressDescription, + ::com::sun::star::table::CellAddress& /* [out] */ _rAddress, + sal_Int16 _nAssumeSheet = -1 + ) const; + + /** creates an address range object from a string representation of a cell range address + */ + bool convertStringAddress( + const ::rtl::OUString& _rAddressDescription, + ::com::sun::star::table::CellRangeAddress& /* [out] */ _rAddress + ) const; + + /** determines if our document is a spreadsheet document, *and* can supply + the given service + */ + bool isSpreadsheetDocumentWhichSupplies( const ::rtl::OUString& _rService ) const SAL_THROW(()); + + /** determines if our document is a spreadsheet document, *and* can supply + the given service + */ + static bool isSpreadsheetDocumentWhichSupplies( + const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument >& _rxDocument, + const ::rtl::OUString& _rService + ) SAL_THROW(()); + + /** checkes whether a given component supports a given servive + */ + bool doesComponentSupport( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent, + const ::rtl::OUString& _rService + ) const; + + /** uses the document (it's factory interface, respectively) to create a component instance + @param _rService + the service name + @param _rArgumentName + the name of the single argument to pass during creation. May be empty, in this case + no arguments are passed + @param _rArgumentValue + the value of the instantiation argument. Not evaluated if <arg>_rArgumentName</arg> + is empty. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + createDocumentDependentInstance( + const ::rtl::OUString& _rService, + const ::rtl::OUString& _rArgumentName, + const ::com::sun::star::uno::Any& _rArgumentValue + ) const; + + /** converts an address representation into another one + + @param _rInputProperty + the input property name for the conversion service + @param _rInputValue + the input property value for the conversion service + @param _rOutputProperty + the output property name for the conversion service + @param _rOutputValue + the output property value for the conversion service + @param _bIsRange + if <TRUE/>, the RangeAddressConversion service will be used, else + the AddressConversion service + + @return + <TRUE/> if any only if the conversion was successfull + + @see com::sun::star::table::CellAddressConversion + @see com::sun::star::table::CellRangeAddressConversion + */ + bool doConvertAddressRepresentations( + const ::rtl::OUString& _rInputProperty, + const ::com::sun::star::uno::Any& _rInputValue, + const ::rtl::OUString& _rOutputProperty, + ::com::sun::star::uno::Any& _rOutputValue, + bool _bIsRange + ) const SAL_THROW(()); + }; + +//............................................................................ +} // namespace xmloff +//............................................................................ + +#endif // XMLOFF_FORMS_FORMCELLBINDING diff --git a/xmloff/source/forms/formenums.cxx b/xmloff/source/forms/formenums.cxx new file mode 100644 index 000000000000..aac623c79482 --- /dev/null +++ b/xmloff/source/forms/formenums.cxx @@ -0,0 +1,348 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "formenums.hxx" +#include <osl/diagnose.h> +#include <com/sun/star/form/FormSubmitEncoding.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/form/NavigationBarMode.hpp> +#include <com/sun/star/form/TabulatorCycle.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/awt/FontWidth.hpp> +#include <com/sun/star/awt/FontEmphasisMark.hpp> +#include <com/sun/star/awt/FontRelief.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/awt/VisualEffect.hpp> +#include <com/sun/star/awt/ImageScaleMode.hpp> +#include <tools/wintypes.hxx> // for check states +#include <xmloff/xmltoken.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::awt; + using namespace ::xmloff::token; + + const SvXMLEnumMapEntry* OEnumMapper::s_pEnumMap[OEnumMapper::KNOWN_ENUM_PROPERTIES] = + { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }; + + //--------------------------------------------------------------------- + const SvXMLEnumMapEntry* OEnumMapper::getEnumMap(EnumProperties _eProperty) + { + OSL_ENSURE(_eProperty < KNOWN_ENUM_PROPERTIES, "OEnumMapper::getEnumMap: invalid index (this will crash)!"); + + const SvXMLEnumMapEntry*& rReturn = s_pEnumMap[_eProperty]; + if (!rReturn) + { + // the map for this property is not initialized yet + switch (_eProperty) + { + // FormSubmitEncoding + case epSubmitEncoding: + { + static SvXMLEnumMapEntry aSubmitEncodingMap[] = + { + { XML_APPLICATION_X_WWW_FORM_URLENCODED, FormSubmitEncoding_URL }, + { XML_MULTIPART_FORMDATA, FormSubmitEncoding_MULTIPART }, + { XML_APPLICATION_TEXT, FormSubmitEncoding_TEXT }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aSubmitEncodingMap; + } + break; + // FormSubmitMethod + case epSubmitMethod: + { + static SvXMLEnumMapEntry aSubmitMethodMap[] = + { + { XML_GET, FormSubmitMethod_GET }, + { XML_POST, FormSubmitMethod_POST }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aSubmitMethodMap; + } + break; + // CommandType + case epCommandType: + { + static SvXMLEnumMapEntry aCommandTypeMap[] = + { + { XML_TABLE, CommandType::TABLE }, + { XML_QUERY, CommandType::QUERY }, + { XML_COMMAND, CommandType::COMMAND }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aCommandTypeMap; + } + break; + // NavigationBarMode + case epNavigationType: + { + static SvXMLEnumMapEntry aNavigationTypeMap[] = + { + { XML_NONE, NavigationBarMode_NONE }, + { XML_CURRENT, NavigationBarMode_CURRENT }, + { XML_PARENT, NavigationBarMode_PARENT }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aNavigationTypeMap; + }; + break; + // TabulatorCycle + case epTabCyle: + { + static SvXMLEnumMapEntry aTabulytorCycleMap[] = + { + { XML_RECORDS, TabulatorCycle_RECORDS }, + { XML_CURRENT, TabulatorCycle_CURRENT }, + { XML_PAGE, TabulatorCycle_PAGE }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aTabulytorCycleMap; + }; + break; + // FormButtonType + case epButtonType: + { + static SvXMLEnumMapEntry aFormButtonTypeMap[] = + { + { XML_PUSH, FormButtonType_PUSH }, + { XML_SUBMIT, FormButtonType_SUBMIT }, + { XML_RESET, FormButtonType_RESET }, + { XML_URL, FormButtonType_URL }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aFormButtonTypeMap; + }; + break; + // ListSourceType + case epListSourceType: + { + static SvXMLEnumMapEntry aListSourceTypeMap[] = + { + { XML_VALUE_LIST, ListSourceType_VALUELIST }, + { XML_TABLE, ListSourceType_TABLE }, + { XML_QUERY, ListSourceType_QUERY }, + { XML_SQL, ListSourceType_SQL }, + { XML_SQL_PASS_THROUGH, ListSourceType_SQLPASSTHROUGH }, + { XML_TABLE_FIELDS, ListSourceType_TABLEFIELDS }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aListSourceTypeMap; + }; + break; + // check state of a checkbox + case epCheckState: + { + static SvXMLEnumMapEntry aCheckStateMap[] = + { + { XML_UNCHECKED, STATE_NOCHECK }, + { XML_CHECKED, STATE_CHECK }, + { XML_UNKNOWN, STATE_DONTKNOW }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aCheckStateMap; + }; + break; + case epTextAlign: + { + static SvXMLEnumMapEntry aTextAlignMap[] = + { + { XML_START, TextAlign::LEFT }, + { XML_CENTER, TextAlign::CENTER }, + { XML_END, TextAlign::RIGHT }, + { XML_JUSTIFY, (sal_uInt16)-1 }, + { XML_JUSTIFIED, (sal_uInt16)-1 }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aTextAlignMap; + }; + break; + case epBorderWidth: + { + static SvXMLEnumMapEntry aBorderTypeMap[] = + { + { XML_NONE, 0 }, + { XML_HIDDEN, 0 }, + { XML_SOLID, 2 }, + { XML_DOUBLE, 2 }, + { XML_DOTTED, 2 }, + { XML_DASHED, 2 }, + { XML_GROOVE, 1 }, + { XML_RIDGE, 1 }, + { XML_INSET, 1 }, + { XML_OUTSET, 1 }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aBorderTypeMap; + }; + break; + + case epFontEmphasis: + { + static SvXMLEnumMapEntry aFontEmphasisMap[] = + { + { XML_NONE, FontEmphasisMark::NONE }, + { XML_DOT, FontEmphasisMark::DOT }, + { XML_CIRCLE, FontEmphasisMark::CIRCLE }, + { XML_DISC, FontEmphasisMark::DISC }, + { XML_ACCENT, FontEmphasisMark::ACCENT }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aFontEmphasisMap; + } + break; + + case epFontRelief: + { + static SvXMLEnumMapEntry aFontReliefMap[] = + { + { XML_NONE, FontRelief::NONE }, + { XML_ENGRAVED, FontRelief::ENGRAVED }, + { XML_EMBOSSED, FontRelief::EMBOSSED }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aFontReliefMap; + } + break; + + case epListLinkageType: + { + static SvXMLEnumMapEntry aListLinkageMap[] = + { + { XML_SELECTION, 0 }, + { XML_SELECTION_INDEXES, 1 }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aListLinkageMap; + } + break; + + case epOrientation: + { + static SvXMLEnumMapEntry aOrientationMap[] = + { + { XML_HORIZONTAL, ScrollBarOrientation::HORIZONTAL }, + { XML_VERTICAL, ScrollBarOrientation::VERTICAL }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aOrientationMap; + } + break; + + case epVisualEffect: + { + static SvXMLEnumMapEntry aVisualEffectMap[] = + { + { XML_NONE, VisualEffect::NONE }, + { XML_3D, VisualEffect::LOOK3D }, + { XML_FLAT, VisualEffect::FLAT }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aVisualEffectMap; + } + break; + + case epImagePosition: + { + static SvXMLEnumMapEntry aImagePositionMap[] = + { + { XML_START, 0 }, + { XML_END, 1 }, + { XML_TOP, 2 }, + { XML_BOTTOM, 3 }, + { XML_CENTER, (sal_uInt16)-1 }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aImagePositionMap; + } + break; + + case epImageAlign: + { + static SvXMLEnumMapEntry aImageAlignMap[] = + { + { XML_START, 0 }, + { XML_CENTER, 1 }, + { XML_END, 2 }, + { XML_TOKEN_INVALID, 0 } + }; + rReturn = aImageAlignMap; + } + break; + + case epImageScaleMode: + { + static const SvXMLEnumMapEntry aScaleModeMap[] = + { + { XML_BACKGROUND_NO_REPEAT, ImageScaleMode::None }, + { XML_REPEAT, ImageScaleMode::None }, // repeating the image is not supported + { XML_STRETCH, ImageScaleMode::Anisotropic }, + { XML_SCALE, ImageScaleMode::Isotropic }, + { XML_TOKEN_INVALID, ImageScaleMode::None } + }; + rReturn = aScaleModeMap; + } + break; + + case KNOWN_ENUM_PROPERTIES: + break; + } + } + + return rReturn; + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/formenums.hxx b/xmloff/source/forms/formenums.hxx new file mode 100644 index 000000000000..215a69b61231 --- /dev/null +++ b/xmloff/source/forms/formenums.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMENUMS_HXX_ +#define _XMLOFF_FORMENUMS_HXX_ + +#include <xmloff/xmlement.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OEnumMapper + //===================================================================== + class OEnumMapper + { + public: + enum EnumProperties + { + epSubmitEncoding = 0, + epSubmitMethod, + epCommandType, + epNavigationType, + epTabCyle, + epButtonType, + epListSourceType, + epCheckState, + epTextAlign, + epBorderWidth, + epFontEmphasis, + epFontRelief, + epListLinkageType, + epOrientation, + epVisualEffect, + epImagePosition, + epImageAlign, + epImageScaleMode, + + KNOWN_ENUM_PROPERTIES + }; + + private: + static const SvXMLEnumMapEntry* s_pEnumMap[KNOWN_ENUM_PROPERTIES]; + + public: + static const SvXMLEnumMapEntry* getEnumMap(EnumProperties _eProperty); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMENUMS_HXX_ + diff --git a/xmloff/source/forms/formevents.cxx b/xmloff/source/forms/formevents.cxx new file mode 100644 index 000000000000..fcccef5065a8 --- /dev/null +++ b/xmloff/source/forms/formevents.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "formevents.hxx" +#include "xmlnmspe.hxx" +#include <xmloff/xmlevent.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= event translation table + //===================================================================== + static const XMLEventNameTranslation aEventTranslations[] = + { + { "XApproveActionListener::approveAction", XML_NAMESPACE_FORM, "approveaction" }, // "on-approveaction" + { "XActionListener::actionPerformed", XML_NAMESPACE_FORM, "performaction" }, // "on-performaction" + { "XChangeListener::changed", XML_NAMESPACE_DOM, "change" }, // "on-change" + { "XTextListener::textChanged", XML_NAMESPACE_FORM, "textchange" }, // "on-textchange" + { "XItemListener::itemStateChanged", XML_NAMESPACE_FORM, "itemstatechange" }, // "on-itemstatechange" + { "XFocusListener::focusGained", XML_NAMESPACE_DOM, "DOMFocusIn" }, // "on-focus" + { "XFocusListener::focusLost", XML_NAMESPACE_DOM, "DOMFocusOut" }, // "on-blur" + { "XKeyListener::keyPressed", XML_NAMESPACE_DOM, "keydown" }, // "on-keydown" + { "XKeyListener::keyReleased", XML_NAMESPACE_DOM, "keyup" }, // "on-keyup" + { "XMouseListener::mouseEntered", XML_NAMESPACE_DOM, "mouseover" }, // "on-mouseover" + { "XMouseMotionListener::mouseDragged", XML_NAMESPACE_FORM, "mousedrag" }, // "on-mousedrag" + { "XMouseMotionListener::mouseMoved", XML_NAMESPACE_DOM, "mousemove" }, // "on-mousemove" + { "XMouseListener::mousePressed", XML_NAMESPACE_DOM, "mousedown" }, // "on-mousedown" + { "XMouseListener::mouseReleased", XML_NAMESPACE_DOM, "mouseup" }, // "on-mouseup" + { "XMouseListener::mouseExited", XML_NAMESPACE_DOM, "mouseout" }, // "on-mouseout" + { "XResetListener::approveReset", XML_NAMESPACE_FORM, "approvereset" }, // "on-approvereset" + { "XResetListener::resetted", XML_NAMESPACE_DOM, "reset" }, // "on-reset" + { "XSubmitListener::approveSubmit", XML_NAMESPACE_DOM, "submit" }, // "on-submit" + { "XUpdateListener::approveUpdate", XML_NAMESPACE_FORM, "approveupdate" }, // "on-approveupdate" + { "XUpdateListener::updated", XML_NAMESPACE_FORM, "update" }, // "on-update" + { "XLoadListener::loaded", XML_NAMESPACE_DOM, "load" }, // "on-load" + { "XLoadListener::reloading", XML_NAMESPACE_FORM, "startreload" }, // "on-startreload" + { "XLoadListener::reloaded", XML_NAMESPACE_FORM, "reload" }, // "on-reload" + { "XLoadListener::unloading", XML_NAMESPACE_FORM, "startunload" }, // "on-startunload" + { "XLoadListener::unloaded", XML_NAMESPACE_DOM, "unload" }, // "on-unload" + { "XConfirmDeleteListener::confirmDelete", XML_NAMESPACE_FORM, "confirmdelete" }, // "on-confirmdelete" + { "XRowSetApproveListener::approveRowChange", XML_NAMESPACE_FORM, "approverowchange" }, // "on-approverowchange" + { "XRowSetListener::rowChanged", XML_NAMESPACE_FORM, "rowchange" }, // "on-rowchange" + { "XRowSetApproveListener::approveCursorMove", XML_NAMESPACE_FORM, "approvecursormove" }, // "on-approvecursormove" + { "XRowSetListener::cursorMoved", XML_NAMESPACE_FORM, "cursormove" }, // "on-cursormove" + { "XDatabaseParameterListener::approveParameter",XML_NAMESPACE_FORM, "supplyparameter" }, // "on-supplyparameter" + { "XSQLErrorListener::errorOccured", XML_NAMESPACE_DOM, "error" }, // "on-error" + { "XAdjustmentListener::adjustmentValueChanged",XML_NAMESPACE_FORM, "adjust" }, // "on-adjust" + { 0, 0, 0 } + }; + + const XMLEventNameTranslation* g_pFormsEventTranslation = aEventTranslations; + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/formevents.hxx b/xmloff/source/forms/formevents.hxx new file mode 100644 index 000000000000..e63d70b0b280 --- /dev/null +++ b/xmloff/source/forms/formevents.hxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_FORMEVENTS_HXX_ +#define _XMLOFF_FORMS_FORMEVENTS_HXX_ + +struct XMLEventNameTranslation; +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= event translation table + //===================================================================== + extern const XMLEventNameTranslation* g_pFormsEventTranslation; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_FORMEVENTS_HXX_ + diff --git a/xmloff/source/forms/formlayerexport.cxx b/xmloff/source/forms/formlayerexport.cxx new file mode 100644 index 000000000000..ad5ff7eb4dae --- /dev/null +++ b/xmloff/source/forms/formlayerexport.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include <stdio.h> +#include <xmloff/formlayerexport.hxx> +#include "strings.hxx" +#include "elementexport.hxx" +#include "xmlnmspe.hxx" +#include <xmloff/xmlexp.hxx> +#include "layerexport.hxx" +#include "propertyexport.hxx" +#include <osl/diagnose.h> +#include <comphelper/extract.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/stl_types.hxx> +#include "officeforms.hxx" + + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::drawing; + using namespace ::com::sun::star::frame; + + //===================================================================== + //= OFormLayerXMLExport + //===================================================================== + + //--------------------------------------------------------------------- + OFormLayerXMLExport::OFormLayerXMLExport(SvXMLExport& _rContext) + :m_rContext(_rContext) + ,m_pImpl(new OFormLayerXMLExport_Impl(_rContext)) + { + } + + //--------------------------------------------------------------------- + OFormLayerXMLExport::~OFormLayerXMLExport() + { + delete m_pImpl; + m_pImpl = NULL; + } + + //--------------------------------------------------------------------- + sal_Bool OFormLayerXMLExport::seekPage(const Reference< XDrawPage >& _rxDrawPage) + { + return m_pImpl->seekPage(_rxDrawPage); + } + + //--------------------------------------------------------------------- + ::rtl::OUString OFormLayerXMLExport::getControlId(const Reference< XPropertySet >& _rxControl) + { + return m_pImpl->getControlId(_rxControl); + } + + //--------------------------------------------------------------------- + ::rtl::OUString OFormLayerXMLExport::getControlNumberStyle( const Reference< XPropertySet >& _rxControl ) + { + return m_pImpl->getControlNumberStyle(_rxControl); + } + + //--------------------------------------------------------------------- + ::vos::ORef< SvXMLExportPropertyMapper > OFormLayerXMLExport::getStylePropertyMapper() + { + return m_pImpl->getStylePropertyMapper(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::initialize() + { + m_pImpl->clear(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::examineForms(const Reference< XDrawPage >& _rxDrawPage) + { + try + { + m_pImpl->examineForms(_rxDrawPage); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OFormLayerXMLExport::examine: could not examine the draw page!"); + } + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::exportForms(const Reference< XDrawPage >& _rxDrawPage) + { + m_pImpl->exportForms(_rxDrawPage); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::exportXForms() const + { + m_pImpl->exportXForms(); + } + + //--------------------------------------------------------------------- + bool OFormLayerXMLExport::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage ) const + { + return m_pImpl->pageContainsForms( _rxDrawPage ); + } + + //--------------------------------------------------------------------- + bool OFormLayerXMLExport::documentContainsXForms() const + { + return m_pImpl->documentContainsXForms(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::exportControlNumberStyles() + { + m_pImpl->exportControlNumberStyles(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::exportAutoControlNumberStyles() + { + m_pImpl->exportAutoControlNumberStyles(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::exportAutoStyles() + { + m_pImpl->exportAutoStyles(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLExport::excludeFromExport( const Reference< XControlModel > _rxControl ) + { + m_pImpl->excludeFromExport( _rxControl ); + } + + //========================================================================= + //= OOfficeFormsExport + //========================================================================= + //------------------------------------------------------------------------- + OOfficeFormsExport::OOfficeFormsExport( SvXMLExport& _rExp ) + :m_pImpl(NULL) + { + m_pImpl = new OFormsRootExport(_rExp); + } + + //------------------------------------------------------------------------- + OOfficeFormsExport::~OOfficeFormsExport() + { + delete m_pImpl; + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/formlayerimport.cxx b/xmloff/source/forms/formlayerimport.cxx new file mode 100644 index 000000000000..a31b6397f51f --- /dev/null +++ b/xmloff/source/forms/formlayerimport.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include <xmloff/formlayerimport.hxx> +#include "layerimport.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + 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::xml; + + //===================================================================== + //= OFormLayerXMLExport + //===================================================================== + + //--------------------------------------------------------------------- + OFormLayerXMLImport::OFormLayerXMLImport(SvXMLImport& _rImporter) + :m_pImpl(NULL) + { + m_pImpl = new OFormLayerXMLImport_Impl(_rImporter); + } + + //--------------------------------------------------------------------- + OFormLayerXMLImport::~OFormLayerXMLImport() + { + delete m_pImpl; + } + + //--------------------------------------------------------------------- + ::vos::ORef< SvXMLImportPropertyMapper > OFormLayerXMLImport::getStylePropertyMapper() const + { + return m_pImpl->getStylePropertyMapper(); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::setAutoStyleContext(SvXMLStylesContext* _pNewContext) + { + m_pImpl->setAutoStyleContext(_pNewContext); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::seekPage(const Reference< XDrawPage >& _rxDrawPage) + { + m_pImpl->seekPage(_rxDrawPage); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::startPage(const Reference< XDrawPage >& _rxDrawPage) + { + m_pImpl->startPage(_rxDrawPage); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::endPage() + { + m_pImpl->endPage(); + } + + //--------------------------------------------------------------------- + Reference< XPropertySet > OFormLayerXMLImport::lookupControl(const ::rtl::OUString& _rId) + { + return m_pImpl->lookupControlId(_rId); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OFormLayerXMLImport::createOfficeFormsContext( + SvXMLImport& _rImport, + sal_uInt16 _nPrefix, + const rtl::OUString& _rLocalName) + { + return m_pImpl->createOfficeFormsContext(_rImport, _nPrefix, _rLocalName); + } + + //--------------------------------------------------------------------- + SvXMLImportContext* OFormLayerXMLImport::createContext(const sal_uInt16 _nPrefix, const rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttribs) + { + return m_pImpl->createContext(_nPrefix, _rLocalName, _rxAttribs); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::applyControlNumberStyle(const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rControlNumerStyleName) + { + m_pImpl->applyControlNumberStyle(_rxControlModel, _rControlNumerStyleName); + } + + //--------------------------------------------------------------------- + void OFormLayerXMLImport::documentDone( ) + { + m_pImpl->documentDone( ); + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/formsimp.cxx b/xmloff/source/forms/formsimp.cxx new file mode 100644 index 000000000000..00a745660710 --- /dev/null +++ b/xmloff/source/forms/formsimp.cxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <xmloff/xmlimp.hxx> +#include "xmlnmspe.hxx" +#include <xmloff/nmspmap.hxx> + +#ifndef _XMLOFF_ANIMIMP_HXX +#include <xmloff/formsimp.hxx> +#endif + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + + +TYPEINIT1( XMLFormsContext, SvXMLImportContext ); + +XMLFormsContext::XMLFormsContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLocalName ) +: SvXMLImportContext(rImport, nPrfx, rLocalName) +{ +} + +XMLFormsContext::~XMLFormsContext() +{ +} + +SvXMLImportContext * XMLFormsContext::CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName, + const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList ) +{ + return GetImport().GetFormImport()->createContext( nPrefix, rLocalName, xAttrList ); +} diff --git a/xmloff/source/forms/formstyles.cxx b/xmloff/source/forms/formstyles.cxx new file mode 100644 index 000000000000..571d113d321f --- /dev/null +++ b/xmloff/source/forms/formstyles.cxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "formstyles.hxx" +#include <xmloff/xmltoken.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace token; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::xml; + + //===================================================================== + //= OControlStyleContext + //===================================================================== + //--------------------------------------------------------------------- + OControlStyleContext::OControlStyleContext( SvXMLImport& _rImport, const sal_uInt16 _Prefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList, SvXMLStylesContext& _rParentStyles, + const sal_uInt16 _nFamily, const sal_Bool _bDefaultStyle ) + :XMLPropStyleContext( _rImport, _Prefix, _rLocalName, _rxAttrList, _rParentStyles, _nFamily, _bDefaultStyle ) + { + } + + //--------------------------------------------------------------------- + void OControlStyleContext::SetAttribute( sal_uInt16 _nPrefixKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue ) + { + if ( _rLocalName == GetXMLToken( XML_DATA_STYLE_NAME ) ) + m_sNumberStyleName = _rValue; + else + XMLPropStyleContext::SetAttribute( _nPrefixKey, _rLocalName, _rValue ); + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/formstyles.hxx b/xmloff/source/forms/formstyles.hxx new file mode 100644 index 000000000000..6510c1e41a92 --- /dev/null +++ b/xmloff/source/forms/formstyles.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef XMLOFF_FORMSTYLES_HXX +#define XMLOFF_FORMSTYLES_HXX + +#include <xmloff/prstylei.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OControlStyleContext + //===================================================================== + class OControlStyleContext : public XMLPropStyleContext + { + protected: + ::rtl::OUString m_sNumberStyleName; + + public: + OControlStyleContext( + SvXMLImport& _rImport, + const sal_uInt16 _Prefix, + const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList, + SvXMLStylesContext& _rParentStyles, + const sal_uInt16 _nFamily, + const sal_Bool _bDefaultStyle + ); + + inline const ::rtl::OUString& getNumberStyleName( ) const { return m_sNumberStyleName; } + + protected: + virtual void SetAttribute( + sal_uInt16 _nPrefixKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue + ); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // XMLOFF_FORMSTYLES_HXX + diff --git a/xmloff/source/forms/gridcolumnproptranslator.cxx b/xmloff/source/forms/gridcolumnproptranslator.cxx new file mode 100644 index 000000000000..b828d258cdd3 --- /dev/null +++ b/xmloff/source/forms/gridcolumnproptranslator.cxx @@ -0,0 +1,345 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "gridcolumnproptranslator.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +/** === end UNO includes === **/ +#include <osl/diagnose.h> +#include <cppuhelper/implbase1.hxx> + +#include <algorithm> + +//........................................................................ +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::style; + + namespace + { + //---------------------------------------------------------------- + ::rtl::OUString getParaAlignProperty() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParaAdjust" ) ); + } + + //---------------------------------------------------------------- + ::rtl::OUString getAlignProperty() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Align" ) ); + } + + //---------------------------------------------------------------- + sal_Int32 findStringElement( const Sequence< ::rtl::OUString >& _rNames, const ::rtl::OUString& _rName ) + { + const ::rtl::OUString* pStart = _rNames.getConstArray(); + const ::rtl::OUString* pEnd = _rNames.getConstArray() + _rNames.getLength(); + const ::rtl::OUString* pPos = ::std::find( pStart, pEnd, _rName ); + if ( pPos != pEnd ) + return pPos - pStart; + return -1; + } + + //---------------------------------------------------------------- + struct AlignmentTranslationEntry + { + ParagraphAdjust nParagraphValue; + sal_Int16 nControlValue; + } + AlignmentTranslations[] = + { + // note that order matters: + // valueAlignToParaAdjust and valueParaAdjustToAlign search this map from the _beginning_ + // and use the first matching entry + { ParagraphAdjust_LEFT, TextAlign::LEFT }, + { ParagraphAdjust_CENTER, TextAlign::CENTER }, + { ParagraphAdjust_RIGHT, TextAlign::RIGHT }, + { ParagraphAdjust_BLOCK, TextAlign::RIGHT }, + { ParagraphAdjust_STRETCH, TextAlign::LEFT }, + { ParagraphAdjust_MAKE_FIXED_SIZE, TextAlign::LEFT }, + { ParagraphAdjust_MAKE_FIXED_SIZE, -1 } + }; + + //---------------------------------------------------------------- + void valueAlignToParaAdjust(Any& rValue) + { + sal_Int16 nValue = 0; + rValue >>= nValue; + const AlignmentTranslationEntry* pTranslation = AlignmentTranslations; + while (-1 != pTranslation->nControlValue) + { + if ( nValue == pTranslation->nControlValue ) + { + rValue <<= pTranslation->nParagraphValue; + return; + } + ++pTranslation; + } + OSL_ENSURE( sal_False, "valueAlignToParaAdjust: unreachable!" ); + } + + //---------------------------------------------------------------- + void valueParaAdjustToAlign(Any& rValue) + { + sal_Int32 nValue = 0; + rValue >>= nValue; + const AlignmentTranslationEntry* pTranslation = AlignmentTranslations; + while ( ParagraphAdjust_MAKE_FIXED_SIZE != pTranslation->nParagraphValue) + { + if ( nValue == pTranslation->nParagraphValue) + { + rValue <<= pTranslation->nControlValue; + return; + } + ++pTranslation; + } + OSL_ENSURE( sal_False, "valueParaAdjustToAlign: unreachable!" ); + } + + //==================================================================== + //= OMergedPropertySetInfo + //==================================================================== + typedef ::cppu::WeakAggImplHelper1 < XPropertySetInfo + > OMergedPropertySetInfo_Base; + class OMergedPropertySetInfo : public OMergedPropertySetInfo_Base + { + private: + Reference< XPropertySetInfo > m_xMasterInfo; + + public: + OMergedPropertySetInfo( const Reference< XPropertySetInfo >& _rxMasterInfo ); + + protected: + virtual ~OMergedPropertySetInfo(); + + // XPropertySetInfo + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > SAL_CALL getProperties( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::beans::Property SAL_CALL getPropertyByName( const ::rtl::OUString& aName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& Name ) throw (::com::sun::star::uno::RuntimeException); + }; + + //---------------------------------------------------------------- + OMergedPropertySetInfo::OMergedPropertySetInfo( const Reference< XPropertySetInfo >& _rxMasterInfo ) + :m_xMasterInfo( _rxMasterInfo ) + { + OSL_ENSURE( m_xMasterInfo.is(), "OMergedPropertySetInfo::OMergedPropertySetInfo: hmm?" ); + } + + //---------------------------------------------------------------- + OMergedPropertySetInfo::~OMergedPropertySetInfo() + { + } + + //---------------------------------------------------------------- + Sequence< Property > SAL_CALL OMergedPropertySetInfo::getProperties( ) throw (RuntimeException) + { + // add a "ParaAdjust" property to the master properties + Sequence< Property > aProperties; + if ( m_xMasterInfo.is() ) + aProperties = m_xMasterInfo->getProperties(); + + sal_Int32 nOldLength = aProperties.getLength(); + aProperties.realloc( nOldLength + 1 ); + aProperties[ nOldLength ] = getPropertyByName( getParaAlignProperty() ); + + return aProperties; + } + + //---------------------------------------------------------------- + Property SAL_CALL OMergedPropertySetInfo::getPropertyByName( const ::rtl::OUString& aName ) throw (UnknownPropertyException, RuntimeException) + { + if ( aName == getParaAlignProperty() ) + return Property( getParaAlignProperty(), -1, + ::getCppuType( static_cast< const ParagraphAdjust* >( NULL ) ), 0 ); + + if ( !m_xMasterInfo.is() ) + return Property(); + + return m_xMasterInfo->getPropertyByName( aName ); + } + + //---------------------------------------------------------------- + ::sal_Bool SAL_CALL OMergedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& Name ) throw (RuntimeException) + { + if ( Name == getParaAlignProperty() ) + return sal_True; + + if ( !m_xMasterInfo.is() ) + return sal_False; + + return m_xMasterInfo->hasPropertyByName( Name ); + } + } + + + //==================================================================== + //= OGridColumnPropertyTranslator + //==================================================================== + //-------------------------------------------------------------------- + OGridColumnPropertyTranslator::OGridColumnPropertyTranslator( const Reference< XMultiPropertySet >& _rxGridColumn ) + :m_xGridColumn( _rxGridColumn ) + { + OSL_ENSURE( m_xGridColumn.is(), "OGridColumnPropertyTranslator: invalid grid column!" ); + } + + //-------------------------------------------------------------------- + OGridColumnPropertyTranslator::~OGridColumnPropertyTranslator() + { + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL OGridColumnPropertyTranslator::getPropertySetInfo( ) throw (RuntimeException) + { + Reference< XPropertySetInfo > xColumnPropInfo; + if ( m_xGridColumn.is() ) + xColumnPropInfo = m_xGridColumn->getPropertySetInfo(); + return new OMergedPropertySetInfo( xColumnPropInfo ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + // we implement this by delegating it to setPropertyValues, which is to ignore unknown properties. On the other hand, our + // contract requires us to throw a UnknownPropertyException for unknown properties, so check this first. + + if ( !getPropertySetInfo()->hasPropertyByName( _rPropertyName ) ) + throw UnknownPropertyException( _rPropertyName, *this ); + + Sequence< ::rtl::OUString > aNames( &_rPropertyName, 1 ); + Sequence< Any > aValues( &aValue, 1 ); + setPropertyValues( aNames, aValues ); + } + + //-------------------------------------------------------------------- + Any SAL_CALL OGridColumnPropertyTranslator::getPropertyValue( const ::rtl::OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + Sequence< ::rtl::OUString > aNames( &PropertyName, 1 ); + Sequence< Any > aValues = getPropertyValues( aNames ); + OSL_ENSURE( aValues.getLength() == 1, "OGridColumnPropertyTranslator::getPropertyValue: nonsense!" ); + if ( aValues.getLength() == 1 ) + return aValues[0]; + return Any(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::addPropertyChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::removePropertyChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::addVetoableChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::removeVetoableChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues ) throw (PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + if ( !m_xGridColumn.is() ) + return; + + // if there's ever the need for more than one property being translated, then we should + // certainly have a more clever implementation than this ... + + Sequence< ::rtl::OUString > aTranslatedNames( aPropertyNames ); + Sequence< Any > aTranslatedValues( aValues ); + + sal_Int32 nParaAlignPos = findStringElement( aTranslatedNames, getParaAlignProperty() ); + if ( nParaAlignPos != -1 ) + { + aTranslatedNames[ nParaAlignPos ] = getAlignProperty(); + valueParaAdjustToAlign( aTranslatedValues[ nParaAlignPos ] ); + } + + m_xGridColumn->setPropertyValues( aTranslatedNames, aTranslatedValues ); + } + + //-------------------------------------------------------------------- + Sequence< Any > SAL_CALL OGridColumnPropertyTranslator::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames ) throw (RuntimeException) + { + Sequence< Any > aValues( aPropertyNames.getLength() ); + if ( !m_xGridColumn.is() ) + return aValues; + + Sequence< ::rtl::OUString > aTranslatedNames( aPropertyNames ); + sal_Int32 nAlignPos = findStringElement( aTranslatedNames, getParaAlignProperty() ); + if ( nAlignPos != -1 ) + aTranslatedNames[ nAlignPos ] = getAlignProperty(); + + aValues = m_xGridColumn->getPropertyValues( aPropertyNames ); + if ( nAlignPos != -1 ) + valueAlignToParaAdjust( aValues[ nAlignPos ] ); + + return aValues; + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) throw (RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::addPropertiesChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& ) throw (RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::removePropertiesChangeListener: not implemented - this should not be needed!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OGridColumnPropertyTranslator::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) throw (RuntimeException) + { + OSL_ENSURE( sal_False, "OGridColumnPropertyTranslator::firePropertiesChangeEvent: not implemented - this should not be needed!" ); + } + +//........................................................................ +} // namespace xmloff +//........................................................................ + diff --git a/xmloff/source/forms/gridcolumnproptranslator.hxx b/xmloff/source/forms/gridcolumnproptranslator.hxx new file mode 100644 index 000000000000..eb619769ea31 --- /dev/null +++ b/xmloff/source/forms/gridcolumnproptranslator.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef XMLOFF_SOURCE_FORMS_GRIDCOLUMNPROPTRANSLATOR_HXX +#define XMLOFF_SOURCE_FORMS_GRIDCOLUMNPROPTRANSLATOR_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase2.hxx> + +//........................................................................ +namespace xmloff +{ +//........................................................................ + + //==================================================================== + //= OGridColumnPropertyTranslator + //==================================================================== + typedef ::cppu::WeakImplHelper2 < ::com::sun::star::beans::XPropertySet + , ::com::sun::star::beans::XMultiPropertySet + > OGridColumnPropertyTranslator_Base; + class OGridColumnPropertyTranslator : public OGridColumnPropertyTranslator_Base + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > + m_xGridColumn; + + public: + OGridColumnPropertyTranslator( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet >& _rxGridColumn + ); + + protected: + virtual ~OGridColumnPropertyTranslator(); + + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XMultiPropertySet + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aValues ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > SAL_CALL getPropertyValues( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertiesChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL firePropertiesChangeEvent( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + }; + +//........................................................................ +} // namespace xmloff +//........................................................................ + +#endif // XMLOFF_SOURCE_FORMS_GRIDCOLUMNPROPTRANSLATOR_HXX + diff --git a/xmloff/source/forms/ifacecompare.hxx b/xmloff/source/forms/ifacecompare.hxx new file mode 100644 index 000000000000..c20c4cf9624e --- /dev/null +++ b/xmloff/source/forms/ifacecompare.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_IFACECOMPARE_HXX_ +#define _XMLOFF_FORMS_IFACECOMPARE_HXX_ + +#include <comphelper/stl_types.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OInterfaceCompare + //===================================================================== + /** is stl-compliant structure for comparing Reference< <iface> > instances + */ + template < class IAFCE > + struct OInterfaceCompare + :public ::std::binary_function < ::com::sun::star::uno::Reference< IAFCE > + , ::com::sun::star::uno::Reference< IAFCE > + , bool + > + { + bool operator() (const ::com::sun::star::uno::Reference< IAFCE >& lhs, const ::com::sun::star::uno::Reference< IAFCE >& rhs) const + { + return lhs.get() < rhs.get(); + // this does not make any sense if you see the semantics of the pointer returned by get: + // It's a pointer to a point in memory where an interface implementation lies. + // But for our purpose (provide a reliable less-operator which can be used with the STL), this is + // sufficient .... + } + }; + + typedef OInterfaceCompare< ::com::sun::star::beans::XPropertySet > OPropertySetCompare; + typedef OInterfaceCompare< ::com::sun::star::drawing::XDrawPage > ODrawPageCompare; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_IFACECOMPARE_HXX_ + diff --git a/xmloff/source/forms/layerexport.cxx b/xmloff/source/forms/layerexport.cxx new file mode 100644 index 000000000000..9d024a3e2c2e --- /dev/null +++ b/xmloff/source/forms/layerexport.cxx @@ -0,0 +1,833 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 "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 "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 +//......................................................................... + + diff --git a/xmloff/source/forms/layerexport.hxx b/xmloff/source/forms/layerexport.hxx new file mode 100644 index 000000000000..3335645c2abf --- /dev/null +++ b/xmloff/source/forms/layerexport.hxx @@ -0,0 +1,320 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_LAYEREXPORT_HXX_ +#define _XMLOFF_FORMS_LAYEREXPORT_HXX_ + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/util/XNumberFormats.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include "callbacks.hxx" +#include "ifacecompare.hxx" +#include <vos/ref.hxx> + +class SvXMLExport; +class SvXMLNumFmtExport; +class XMLPropertyHandlerFactory; +class SvXMLExportPropertyMapper; + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + typedef ::std::set < ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + , OPropertySetCompare + > PropertySetBag; + + // maps objects (property sets) to strings, e.g. control ids. + typedef ::std::map < ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + , ::rtl::OUString + , OPropertySetCompare + > MapPropertySet2String; + + // map pages to maps (of property sets to strings) + typedef ::std::map < ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > + , MapPropertySet2String + , ODrawPageCompare + > MapPropertySet2Map; + + //===================================================================== + //= OFormLayerXMLExport_Impl + //===================================================================== + /** the implementation class for OFormLayerXMLExport + */ + class OFormLayerXMLExport_Impl + :public IFormsExportContext + { + friend class OFormLayerXMLExport; + + protected: + SvXMLExport& m_rContext; + SvXMLNumFmtExport* m_pControlNumberStyles; + + // ignore list for control models + PropertySetBag m_aIgnoreList; + + // style handling + ::vos::ORef< XMLPropertyHandlerFactory > m_xPropertyHandlerFactory; + ::vos::ORef< SvXMLExportPropertyMapper > m_xStyleExportMapper; + + // we need our own number formats supplier: + // Controls which have a number formats do not work with the formats supplier of the document they reside + // in, instead they use the formats of the data source their form is associated with. If there is no + // such form or no such data source, they work with an own formatter. + // Even more, time and date fields do not work with a central formatter at all, they have their own one + // (which is shared internally, but this is a (hidden) implementation detail.) + // + // To not contaminate the global (document) number formats supplier (which could be obtained from the context), + // we have an own one. + // (Contaminate means: If a user adds a user-defined format to a formatted field, this format is stored in + // in the data source's formats supplier. To export this _and_ reuse existing structures, we would need to + // add this format to the global (document) formats supplier. + // In case of an export we could do some cleanup afterwards, but in case of an import, there is no such + // chance, as (if other user-defined formats exist in the document as well) we can't distinguish + // between user-defined formats really needed for the doc (i.e. in a calc cell) and formats only added + // to the supplier because the controls needed it. + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormats > + m_xControlNumberFormats; + + MapPropertySet2Map m_aControlIds; + // the control ids of all controls on all pages we ever examined + + MapPropertySet2Map m_aReferringControls; + // for a given page (iter->first), and a given control (iter->second->first), this is the comma-separated + // lists of ids of the controls refering to the control given. + + MapPropertySet2Map::iterator + m_aCurrentPageIds; + // the iterator for the control id map for the page beeing handled + MapPropertySet2Map::iterator + m_aCurrentPageReferring; + // the same for the map of referring controls + + // TODO: To avoid this construct above, and to have a cleaner implementation, an class encapsulating the + // export of a single page should be introduced. + + DECLARE_STL_MAP( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >, sal_Int32, OPropertySetCompare, MapPropertySet2Int); + MapPropertySet2Int m_aControlNumberFormats; + // maps controls to format keys, which are relative to our own formats supplier + + MapPropertySet2String m_aGridColumnStyles; + // style names of grid columns + + public: + OFormLayerXMLExport_Impl(SvXMLExport& _rContext); + virtual ~OFormLayerXMLExport_Impl(); + + protected: + /** exports one single grid column + */ + void exportGridColumn( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxColumn, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ); + + /** exports one single control + */ + void exportControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ); + + /** exports one single form + */ + void exportForm(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxProps, + const ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor >& _rEvents + ); + + /** seek to the page given. + + <p>This must be called before you can retrieve any ids for controls on the page.</p> + + @see + getControlId + */ + sal_Bool seekPage( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage); + + /** get the id of the given control. + + <p>You must have sought to the page of the control before calling this.</p> + */ + ::rtl::OUString + getControlId(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl); + + /** retrieves the style name for the control's number style. + + <p>For performance reasons, this method is allowed to be called for any controls, even those which + do not have a number style. In this case, an empty string is returned.</p> + */ + ::rtl::OUString + getControlNumberStyle( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl ); + + // IFormsExportContext + virtual void exportCollectionElements(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& _rxCollection); + virtual SvXMLExport& getGlobalContext(); + virtual ::rtl::OUString getObjectStyleName( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject ); + virtual ::vos::ORef< SvXMLExportPropertyMapper > getStylePropertyMapper(); + + /** clear any structures which have been build in the recent <method>examine</method> calls. + */ + void clear(); + + /** examine a forms collection. + + <p>The method will collect control ids and add styles to the export context as necessary.</p> + + <p>Every control in the object hierarchy given will be assigned to a unique id, which is stored for later + use.</p> + + <p>In addition, any references the controls may have between each other, are collected and stored for + later use.</p> + + <p>Upon calling this method, the id map will be cleared before collecting the new ids, so any ids + you collected previously will be lost</p> + + @param _rxDrawPage + the draw page which's forms collection should be examined + + @see getControlId + @see exportControl + @see exportForms + */ + void examineForms( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage); + + /** export a forms collection of a draw page + + <p>The method will obtain the forms collection of the page and call + <method>exportCollectionElements</method>.</p> + */ + void exportForms( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage); + + /** exports the XForms model data + */ + void exportXForms() const; + + /** determines whether the given page contains logical forms + */ + bool pageContainsForms( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage ) const; + + /** determines whether the given page contains XForm instances + */ + bool documentContainsXForms() const; + + /** exports the controls number styles + */ + void exportControlNumberStyles(); + + /** exports the automatic control number styles + */ + void exportAutoControlNumberStyles(); + + /** exports the auto-styles collected during the examineForms calls + */ + void exportAutoStyles(); + + protected: + sal_Bool impl_isFormPageContainingForms( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage, + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& _rxForms); + + /** moves the m_aCurrentPage* members to the positions specifying the given page. + + @return <TRUE/> if there already were structures for the given page + */ + sal_Bool implMoveIterators( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage, + sal_Bool _bClear); + + /** check the object given if it's a control, if so, examine it. + @return <TRUE/> if the object has been handled + */ + sal_Bool checkExamineControl(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject); + + /** examines the control's number format, so later the format style can be referred + + <p>remembers the format key for the control, so it can later be asked for in getControlNumberStyle</p> + */ + void examineControlNumberFormat(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl); + + /** examines the control's number format, so later the format style can be referred + + <p>does not remember the information returned in any way</p> + */ + sal_Int32 implExamineControlNumberFormat( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject ); + + /** collects AutoStyles for grid columns + */ + void collectGridColumnStylesAndIds( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl ); + + /** ensures that the number format of the given control exist in our own formats supplier. + + <p>The given control is examined for it's format (i.e. it's FormatKey/FormatsSupplier properties), + and the format is added (if necessary) to m_xControlNumberFormats</p>. + + @return + the format key of the control's format relative to our own formats supplier + + */ + sal_Int32 ensureTranslateFormat(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxFormattedControl); + + /// returns the instance exporting our control's number styles + SvXMLNumFmtExport* getControlNumberStyleExport(); + + /// ensures that the instance exporting our control's number styles exists + void ensureControlNumberStyleExport(); + + /** determines the number format style for the given object without remembering it + */ + ::rtl::OUString + getImmediateNumberStyle( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject ); + + /** returns the prefix to be used for control number styles + */ + static const ::rtl::OUString& getControlNumberStyleNamePrefix(); + + /** exclude the given control (model) from export. + + <p>If your document contains form controls which are not to be exported for whatever reason, + you need to announce the models of these controls (can be retrieved from XControlShape::getControl) + to the form layer exporter.<br/> + Of course you have to do this before calling <member>exportForms</member></p> + */ + void excludeFromExport( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > _rxControl ); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_LAYEREXPORT_HXX_ + diff --git a/xmloff/source/forms/layerimport.cxx b/xmloff/source/forms/layerimport.cxx new file mode 100644 index 000000000000..77d60f83ee49 --- /dev/null +++ b/xmloff/source/forms/layerimport.cxx @@ -0,0 +1,657 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "layerimport.hxx" +#include "formenums.hxx" +#include "elementimport.hxx" +#include "officeforms.hxx" +#include "strings.hxx" +#include "formstyles.hxx" +#include <xmloff/xmlictxt.hxx> +#include <xmloff/xmlstyle.hxx> +#include <xmloff/families.hxx> +#include <xmloff/xmlprmap.hxx> +#include <xmloff/prstylei.hxx> +#include <xmloff/xmlimp.hxx> +#include "XMLEventImportHelper.hxx" +#include <xmloff/xmlimppr.hxx> +#include <xmloff/xmlnumfi.hxx> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/form/FormSubmitEncoding.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/form/NavigationBarMode.hpp> +#include <com/sun/star/form/TabulatorCycle.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/awt/VisualEffect.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <tools/wintypes.hxx> // for check states +#include <com/sun/star/lang/Locale.hpp> +#include <xmloff/controlpropertyhdl.hxx> +#include "controlpropertymap.hxx" +#include "formevents.hxx" +#include "formcellbinding.hxx" +#include "xformsimport.hxx" +#include <xmloff/xmltoken.hxx> +#include "xmlnmspe.hxx" +#include <rtl/logfile.hxx> +#include <algorithm> + +SV_IMPL_REF( SvXMLStylesContext ); + +//......................................................................... +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::xml; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::sdb; + +//===================================================================== +//= OFormLayerXMLImport_Impl +//===================================================================== +//--------------------------------------------------------------------- +OFormLayerXMLImport_Impl::OFormLayerXMLImport_Impl(SvXMLImport& _rImporter) + :m_rImporter(_rImporter) + ,m_pAutoStyles(NULL) +{ + // build the attribute2property map + // string properties which are exported as attributes + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_NAME), PROPERTY_NAME); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_IMAGE_DATA), PROPERTY_IMAGEURL); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL), PROPERTY_LABEL); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_LOCATION), PROPERTY_TARGETURL); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_TITLE), PROPERTY_TITLE); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank"); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getDatabaseAttributeName(DA_DATA_FIELD), PROPERTY_DATAFIELD); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getFormAttributeName(faCommand), PROPERTY_COMMAND); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getFormAttributeName(faDatasource), PROPERTY_DATASOURCENAME); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getFormAttributeName(faFilter), PROPERTY_FILTER); + m_aAttributeMetaData.addStringProperty( + OAttributeMetaData::getFormAttributeName(faOrder), PROPERTY_ORDER); + + // properties not added because they're already present in another form + OSL_ENSURE( + 0 == ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_LOCATION)).compareToAscii( + OAttributeMetaData::getFormAttributeName(faAction)), + "OFormLayerXMLImport_Impl::OFormLayerXMLImport_Impl: invalid attribute names (1)!"); + // if this fails, we would have to add a translation from faAction->PROPERTY_TARGETURL + // We did not because we already have one CCA_TARGET_LOCATION->PROPERTY_TARGETURL, + // and CCA_TARGET_LOCATION and faAction should be represented by the same attribute + + OSL_ENSURE( + 0 == ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_NAME)).compareToAscii( + OAttributeMetaData::getFormAttributeName(faName)), + "OFormLayerXMLImport_Impl::OFormLayerXMLImport_Impl: invalid attribute names (2)!"); + // the same for faName, CCA_NAME and PROPERTY_NAME + + // boolean properties which are exported as attributes + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED), PROPERTY_STATE, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_DISABLED), PROPERTY_ENABLED, sal_False, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_DROPDOWN), PROPERTY_DROPDOWN, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_PRINTABLE), PROPERTY_PRINTABLE, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_READONLY), PROPERTY_READONLY, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED), PROPERTY_DEFAULT_STATE, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_TAB_STOP), PROPERTY_TABSTOP, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getDatabaseAttributeName(DA_CONVERT_EMPTY), PROPERTY_EMPTY_IS_NULL, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_VALIDATION), PROPERTY_STRICTFORMAT, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_MULTI_LINE), PROPERTY_MULTILINE, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_AUTOMATIC_COMPLETION), PROPERTY_AUTOCOMPLETE, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_MULTIPLE), PROPERTY_MULTISELECTION, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_DEFAULT_BUTTON), PROPERTY_DEFAULTBUTTON, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_IS_TRISTATE), PROPERTY_TRISTATE, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faAllowDeletes), PROPERTY_ALLOWDELETES, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faAllowInserts), PROPERTY_ALLOWINSERTS, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faAllowUpdates), PROPERTY_ALLOWUPDATES, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faApplyFilter), PROPERTY_APPLYFILTER, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faEscapeProcessing), PROPERTY_ESCAPEPROCESSING, sal_True); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getFormAttributeName(faIgnoreResult), PROPERTY_IGNORERESULT, sal_False); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName( SCA_TOGGLE ), PROPERTY_TOGGLE, sal_False ); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getSpecialAttributeName( SCA_FOCUS_ON_CLICK ), PROPERTY_FOCUS_ON_CLICK, sal_True ); + m_aAttributeMetaData.addBooleanProperty( + OAttributeMetaData::getDatabaseAttributeName( DA_INPUT_REQUIRED ), PROPERTY_INPUT_REQUIRED, sal_False ); + + // the int16 attributes + m_aAttributeMetaData.addInt16Property( + OAttributeMetaData::getCommonControlAttributeName(CCA_MAX_LENGTH), PROPERTY_MAXTEXTLENGTH, 0); + m_aAttributeMetaData.addInt16Property( + OAttributeMetaData::getCommonControlAttributeName(CCA_SIZE), PROPERTY_LINECOUNT, 5); + m_aAttributeMetaData.addInt16Property( + OAttributeMetaData::getCommonControlAttributeName(CCA_TAB_INDEX), PROPERTY_TABINDEX, 0); + m_aAttributeMetaData.addInt16Property( + OAttributeMetaData::getDatabaseAttributeName(DA_BOUND_COLUMN), PROPERTY_BOUNDCOLUMN, 0); + + // the int32 attributes + m_aAttributeMetaData.addInt32Property( + OAttributeMetaData::getSpecialAttributeName( SCA_PAGE_STEP_SIZE ), PROPERTY_BLOCK_INCREMENT, 10 ); + + // the enum attributes + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getCommonControlAttributeName( CCA_VISUAL_EFFECT ), PROPERTY_VISUAL_EFFECT, + VisualEffect::LOOK3D, OEnumMapper::getEnumMap( OEnumMapper::epVisualEffect ), + &::getCppuType( static_cast< sal_Int16* >( NULL ) ) ); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getCommonControlAttributeName( CCA_ORIENTATION ), PROPERTY_ORIENTATION, + ScrollBarOrientation::HORIZONTAL, OEnumMapper::getEnumMap( OEnumMapper::epOrientation ), + &::getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getCommonControlAttributeName(CCA_BUTTON_TYPE), PROPERTY_BUTTONTYPE, + FormButtonType_PUSH, OEnumMapper::getEnumMap(OEnumMapper::epButtonType), + &::getCppuType( static_cast<FormButtonType*>(NULL) )); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE_TYPE), PROPERTY_LISTSOURCETYPE, + ListSourceType_VALUELIST, OEnumMapper::getEnumMap(OEnumMapper::epListSourceType), + &::getCppuType( static_cast<ListSourceType*>(NULL) )); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_STATE), PROPERTY_DEFAULT_STATE, STATE_NOCHECK, + OEnumMapper::getEnumMap(OEnumMapper::epCheckState), + &::getCppuType( static_cast< sal_Int16* >(NULL))); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getSpecialAttributeName(SCA_CURRENT_STATE), PROPERTY_STATE, STATE_NOCHECK, + OEnumMapper::getEnumMap(OEnumMapper::epCheckState), + &::getCppuType( static_cast< sal_Int16* >(NULL))); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getFormAttributeName(faEnctype), PROPERTY_SUBMIT_ENCODING, + FormSubmitEncoding_URL, OEnumMapper::getEnumMap(OEnumMapper::epSubmitEncoding), + &::getCppuType( static_cast<FormSubmitEncoding*>(NULL) )); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getFormAttributeName(faMethod), PROPERTY_SUBMIT_METHOD, + FormSubmitMethod_GET, OEnumMapper::getEnumMap(OEnumMapper::epSubmitMethod), + &::getCppuType( static_cast<FormSubmitMethod*>(NULL) )); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getFormAttributeName(faCommandType), PROPERTY_COMMAND_TYPE, + CommandType::COMMAND, OEnumMapper::getEnumMap(OEnumMapper::epCommandType)); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getFormAttributeName(faNavigationMode), PROPERTY_NAVIGATION, + NavigationBarMode_NONE, OEnumMapper::getEnumMap(OEnumMapper::epNavigationType), + &::getCppuType( static_cast<NavigationBarMode*>(NULL) )); + m_aAttributeMetaData.addEnumProperty( + OAttributeMetaData::getFormAttributeName(faTabbingCycle), PROPERTY_CYCLE, + TabulatorCycle_RECORDS, OEnumMapper::getEnumMap(OEnumMapper::epTabCyle), + &::getCppuType( static_cast<TabulatorCycle*>(NULL) )); + + // initialize our style map + m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory(); + ::vos::ORef< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper(getControlStylePropertyMap(), m_xPropertyHandlerFactory.getBodyPtr()); + m_xImportMapper = new SvXMLImportPropertyMapper(xStylePropertiesMapper.getBodyPtr(), _rImporter); + + // 'initialize' + m_aCurrentPageIds = m_aControlIds.end(); +} + +//--------------------------------------------------------------------- +OFormLayerXMLImport_Impl::~OFormLayerXMLImport_Impl() +{ + // outlined to allow forward declaration of OAttribute2Property in the header + + if (m_pAutoStyles) + m_pAutoStyles->ReleaseRef(); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::setAutoStyleContext(SvXMLStylesContext* _pNewContext) +{ + OSL_ENSURE(!m_pAutoStyles, "OFormLayerXMLImport_Impl::setAutoStyleContext: not to be called twice!"); + m_pAutoStyles = _pNewContext; + if (m_pAutoStyles) + m_pAutoStyles->AddRef(); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::applyControlNumberStyle(const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rControlNumerStyleName) +{ + OSL_ENSURE(_rxControlModel.is() && (0 != _rControlNumerStyleName.getLength()), + "OFormLayerXMLImport_Impl::applyControlNumberStyle: invalid arguments (this will crash)!"); + + OSL_ENSURE(m_pAutoStyles, "OFormLayerXMLImport_Impl::applyControlNumberStyle: have no auto style context!"); + if (!m_pAutoStyles) + { + m_pAutoStyles = m_rImporter.GetShapeImport()->GetAutoStylesContext(); + if (m_pAutoStyles) + m_pAutoStyles->AddRef(); + } + + if (m_pAutoStyles) + { + const SvXMLStyleContext* pStyle = m_pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, _rControlNumerStyleName); + if (pStyle) + { + const SvXMLNumFormatContext* pDataStyle = static_cast<const SvXMLNumFormatContext*>(pStyle); + + // set this format at the control model + try + { + // the models number format supplier and formats + Reference< XNumberFormatsSupplier > xFormatsSupplier; + _rxControlModel->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xFormatsSupplier; + Reference< XNumberFormats > xFormats; + if (xFormatsSupplier.is()) + xFormats = xFormatsSupplier->getNumberFormats(); + OSL_ENSURE(xFormats.is(), "OFormLayerXMLImport_Impl::applyControlNumberStyle: could not obtain the controls number formats!"); + + // obtain a key + if (xFormats.is()) + { + sal_Int32 nFormatKey = const_cast<SvXMLNumFormatContext*>(pDataStyle)->CreateAndInsert( xFormatsSupplier ); + OSL_ENSURE(-1 != nFormatKey, "OFormLayerXMLImport_Impl::applyControlNumberStyle: could not obtain a format key!"); + + // set the format on the control model + _rxControlModel->setPropertyValue(PROPERTY_FORMATKEY, makeAny(nFormatKey)); + } + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OFormLayerXMLImport_Impl::applyControlNumberStyle: couldn't set the format!"); + } + } + else + OSL_ENSURE(sal_False, "OFormLayerXMLImport_Impl::applyControlNumberStyle: did not find the style with the given name!"); + } +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerCellValueBinding( const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rCellAddress ) +{ + OSL_ENSURE( _rxControlModel.is() && _rCellAddress.getLength(), + "OFormLayerXMLImport_Impl::registerCellValueBinding: invalid arguments!" ); + m_aCellValueBindings.push_back( ModelStringPair( _rxControlModel, _rCellAddress ) ); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerXFormsValueBinding( + const Reference< XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rBindingID ) +{ + // TODO: is an empty binding name allowed? + OSL_ENSURE( _rxControlModel.is(), "need model" ); + + m_aXFormsValueBindings.push_back( + ModelStringPair( _rxControlModel, _rBindingID ) ); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerXFormsListBinding( + const Reference< XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rBindingID ) +{ + // TODO: is an empty binding name allowed? + OSL_ENSURE( _rxControlModel.is(), "need model" ); + + m_aXFormsListBindings.push_back( + ModelStringPair( _rxControlModel, _rBindingID ) ); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerXFormsSubmission( + const Reference< XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rSubmissionID ) +{ + // TODO: is an empty binding name allowed? + OSL_ENSURE( _rxControlModel.is(), "need model" ); + + m_aXFormsSubmissions.push_back( + ModelStringPair( _rxControlModel, _rSubmissionID ) ); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerCellRangeListSource( const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rCellRangeAddress ) +{ + OSL_ENSURE( _rxControlModel.is() && _rCellRangeAddress.getLength(), + "OFormLayerXMLImport_Impl::registerCellRangeListSource: invalid arguments!" ); + m_aCellRangeListSources.push_back( ModelStringPair( _rxControlModel, _rCellRangeAddress ) ); +} +//--------------------------------------------------------------------- +const SvXMLStyleContext* OFormLayerXMLImport_Impl::getStyleElement(const ::rtl::OUString& _rStyleName) const +{ + OSL_ENSURE( m_pAutoStyles, "OFormLayerXMLImport_Impl::getStyleElement: have no auto style context!" ); + // did you use setAutoStyleContext? + + const SvXMLStyleContext* pControlStyle = + m_pAutoStyles ? m_pAutoStyles->FindStyleChildContext( XML_STYLE_FAMILY_TEXT_PARAGRAPH, _rStyleName ) : NULL; + OSL_ENSURE( pControlStyle || !m_pAutoStyles, + ::rtl::OString( "OFormLayerXMLImport_Impl::getStyleElement: did not find the style named \"" ) + += ::rtl::OString( _rStyleName.getStr(), _rStyleName.getLength(), RTL_TEXTENCODING_ASCII_US ) + += ::rtl::OString( "\"!" ) ); + return pControlStyle; +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::enterEventContext() +{ + // install our own translation table. We need to disable the other tables because of name conflicts. + m_rImporter.GetEventImport().PushTranslationTable(); + m_rImporter.GetEventImport().AddTranslationTable(g_pFormsEventTranslation); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::leaveEventContext() +{ + // install the original event tables. + m_rImporter.GetEventImport().PopTranslationTable(); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerControlId(const Reference< XPropertySet >& _rxControl, const ::rtl::OUString& _rId) +{ + OSL_ENSURE(m_aCurrentPageIds != m_aControlIds.end(), "OFormLayerXMLImport_Impl::registerControlId: no current page!"); + OSL_ENSURE(_rId.getLength(), "OFormLayerXMLImport_Impl::registerControlId: invalid (empty) control id!"); + + OSL_ENSURE(m_aCurrentPageIds->second.end() == m_aCurrentPageIds->second.find(_rId), "OFormLayerXMLImport_Impl::registerControlId: control id already used!"); + m_aCurrentPageIds->second[_rId] = _rxControl; +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::registerControlReferences(const Reference< XPropertySet >& _rxControl, const ::rtl::OUString& _rReferringControls) +{ + OSL_ENSURE(_rReferringControls.getLength(), "OFormLayerXMLImport_Impl::registerControlReferences: invalid (empty) control id list!"); + OSL_ENSURE(_rxControl.is(), "OFormLayerXMLImport_Impl::registerControlReferences: invalid (NULL) control!"); + m_aControlReferences.push_back( ModelStringPair( _rxControl, _rReferringControls ) ); +} + +//--------------------------------------------------------------------- +::vos::ORef< SvXMLImportPropertyMapper > OFormLayerXMLImport_Impl::getStylePropertyMapper() const +{ + return m_xImportMapper; +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::startPage(const Reference< XDrawPage >& _rxDrawPage) +{ + m_xCurrentPageFormsSupp.clear(); + + OSL_ENSURE(_rxDrawPage.is(), "OFormLayerXMLImport_Impl::startPage: NULL page!"); + m_xCurrentPageFormsSupp = m_xCurrentPageFormsSupp.query( _rxDrawPage ); + OSL_ENSURE( m_xCurrentPageFormsSupp.is(), "OFormLayerXMLImport_Impl::startPage: invalid draw page (no XFormsSupplier)!" ); + if ( !m_xCurrentPageFormsSupp.is() ) + return; + + // add a new entry to our page map + ::std::pair< MapDrawPage2MapIterator, bool > aPagePosition; + aPagePosition = + m_aControlIds.insert(MapDrawPage2Map::value_type(_rxDrawPage, MapString2PropertySet())); + OSL_ENSURE(aPagePosition.second, "OFormLayerXMLImport_Impl::startPage: already imported this page!"); + m_aCurrentPageIds = aPagePosition.first; +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::endPage() +{ + OSL_ENSURE( m_xCurrentPageFormsSupp.is(), "OFormLayerXMLImport_Impl::endPage: sure you called startPage before?" ); + + // do some knittings for the controls which are referring to each other + try + { + static const sal_Unicode s_nSeparator = ','; + ::rtl::OUString sReferring; + ::rtl::OUString sCurrentReferring; + ::rtl::OUString sSeparator(&s_nSeparator, 1); + Reference< XPropertySet > xCurrentReferring; + sal_Int32 nSeparator, nPrevSep; + ::std::vector< ModelStringPair >::const_iterator aEnd = m_aControlReferences.end(); + for ( ::std::vector< ModelStringPair >::const_iterator aReferences = m_aControlReferences.begin(); + aReferences != aEnd; + ++aReferences + ) + { + // the list of control ids is comma separated + + // in a list of n ids there are only n-1 separators ... have to catch this last id + // -> normalize the list + sReferring = aReferences->second; + sReferring += sSeparator; + + nPrevSep = -1; + while (-1 != (nSeparator = sReferring.indexOf(s_nSeparator, nPrevSep + 1))) + { + sCurrentReferring = sReferring.copy(nPrevSep + 1, nSeparator - nPrevSep - 1); + xCurrentReferring = lookupControlId(sCurrentReferring); + if (xCurrentReferring.is()) + // if this condition fails, this is an error, but lookupControlId should have asserted this ... + xCurrentReferring->setPropertyValue( PROPERTY_CONTROLLABEL, makeAny( aReferences->first ) ); + + nPrevSep = nSeparator; + } + } + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OFormLayerXMLImport_Impl::endPage: unable to knit the control references (caught an exception)!"); + } + + // now that we have all children of the forms collection, attach the events + Reference< XIndexAccess > xIndexContainer; + if ( m_xCurrentPageFormsSupp.is() && m_xCurrentPageFormsSupp->hasForms() ) + xIndexContainer = xIndexContainer.query( m_xCurrentPageFormsSupp->getForms() ); + if ( xIndexContainer.is() ) + ODefaultEventAttacherManager::setEvents( xIndexContainer ); + + // clear the structures for the control references. + m_aControlReferences.clear(); + + // and no we have no current page anymore + m_aCurrentPageIds = m_aControlIds.end(); +} + +//--------------------------------------------------------------------- +Reference< XPropertySet > OFormLayerXMLImport_Impl::lookupControlId(const ::rtl::OUString& _rControlId) +{ + OSL_ENSURE(m_aCurrentPageIds != m_aControlIds.end(), "OFormLayerXMLImport_Impl::lookupControlId: no current page!"); + Reference< XPropertySet > xReturn; + if (m_aCurrentPageIds != m_aControlIds.end()) + { + ConstMapString2PropertySetIterator aPos = m_aCurrentPageIds->second.find(_rControlId); + if (m_aCurrentPageIds->second.end() != aPos) + xReturn = aPos->second; + else + OSL_ENSURE(sal_False, "OFormLayerXMLImport_Impl::lookupControlId: invalid control id (did not find it)!"); + } + return xReturn; +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OFormLayerXMLImport_Impl::createOfficeFormsContext( + SvXMLImport& _rImport, + sal_uInt16 _nPrefix, + const rtl::OUString& _rLocalName) +{ + return new OFormsRootImport( _rImport, _nPrefix, _rLocalName ); +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OFormLayerXMLImport_Impl::createContext(const sal_uInt16 _nPrefix, const rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >&) +{ + SvXMLImportContext* pContext = NULL; + if ( 0 == _rLocalName.compareToAscii( "form" ) ) + { + if ( m_xCurrentPageFormsSupp.is() ) + pContext = new OFormImport(*this, *this, _nPrefix, _rLocalName, m_xCurrentPageFormsSupp->getForms() ); + } + else if ( ( _nPrefix == XML_NAMESPACE_XFORMS + && ( xmloff::token::IsXMLToken( _rLocalName, xmloff::token::XML_MODEL ) ) ) + ) + { + pContext = createXFormsModelContext( m_rImporter, _nPrefix, _rLocalName ); + } + + if ( !pContext ) + { + OSL_ENSURE( false, "unknown element" ); + pContext = + new SvXMLImportContext(m_rImporter, _nPrefix, _rLocalName); + } + + return pContext; +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage) +{ + OSL_ENSURE(m_aCurrentPageIds == m_aControlIds.end(), "OFormLayerXMLImport_Impl::seekPage: importing another page currently! This will smash your import!"); + m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage); + OSL_ENSURE(m_aCurrentPageIds != m_aControlIds.end(), "OFormLayerXMLImport_Impl::seekPage: did not find the given page (perhaps it has not been imported, yet?)!"); +} + +//--------------------------------------------------------------------- +void OFormLayerXMLImport_Impl::documentDone( ) +{ + SvXMLImport& rImport = getGlobalContext(); + if ( ( rImport.getImportFlags() & IMPORT_CONTENT ) == 0 ) + return; + + // create (and bind) the spreadsheet cell bindings + if ( !m_aCellValueBindings.empty() + && FormCellBindingHelper::isCellBindingAllowed( rImport.GetModel() ) + ) + { + static ::rtl::OUString s_sIndex( RTL_CONSTASCII_USTRINGPARAM( ":index" ) ); + ::std::vector< ModelStringPair >::const_iterator aEnd = m_aCellValueBindings.end(); + for ( ::std::vector< ModelStringPair >::const_iterator aCellBindings = m_aCellValueBindings.begin(); + aCellBindings != aEnd; + ++aCellBindings + ) + { + try + { + FormCellBindingHelper aHelper( aCellBindings->first, rImport.GetModel() ); + OSL_ENSURE( aHelper.isCellBindingAllowed(), "OFormLayerXMLImport_Impl::documentDone: can't bind this control model!" ); + if ( aHelper.isCellBindingAllowed() ) + { + // There are special bindings for listboxes. See + // OListAndComboImport::doRegisterCellValueBinding for a comment on this HACK. + ::rtl::OUString sBoundCellAddress( aCellBindings->second ); + sal_Int32 nIndicator = sBoundCellAddress.lastIndexOf( s_sIndex ); + + bool bUseIndexBinding = false; + if ( nIndicator != -1 ) + { + sBoundCellAddress = sBoundCellAddress.copy( 0, nIndicator ); + bUseIndexBinding = true; + } + + aHelper.setBinding( aHelper.createCellBindingFromStringAddress( sBoundCellAddress, bUseIndexBinding ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OFormLayerXMLImport_Impl::documentDone: caught an exception while binding to a cell!" ); + } + } + m_aCellValueBindings.clear(); + } + + // the same for the spreadsheet cell range list sources + if ( !m_aCellRangeListSources.empty() + && FormCellBindingHelper::isListCellRangeAllowed( rImport.GetModel() ) + ) + { + for ( ::std::vector< ModelStringPair >::const_iterator aRangeBindings = m_aCellRangeListSources.begin(); + aRangeBindings != m_aCellRangeListSources.end(); + ++aRangeBindings + ) + { + try + { + FormCellBindingHelper aHelper( aRangeBindings->first, rImport.GetModel() ); + OSL_ENSURE( aHelper.isListCellRangeAllowed(), "OFormLayerXMLImport_Impl::documentDone: can't bind this control model!" ); + if ( aHelper.isListCellRangeAllowed() ) + { + aHelper.setListSource( aHelper.createCellListSourceFromStringAddress( aRangeBindings->second ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OFormLayerXMLImport_Impl::documentDone: caught an exception while binding to a cell range!" ); + } + } + m_aCellRangeListSources.clear(); + } + + // process XForms-bindings; call registerXFormsValueBinding for each + std::for_each( m_aXFormsValueBindings.begin(), + m_aXFormsValueBindings.end(), + bind1st( ptr_fun( bindXFormsValueBinding ), + rImport.GetModel() ) ); + // same for list bindings + std::for_each( m_aXFormsListBindings.begin(), + m_aXFormsListBindings.end(), + bind1st( ptr_fun( bindXFormsListBinding ), + rImport.GetModel() ) ); + // same for submissions + std::for_each( m_aXFormsSubmissions.begin(), + m_aXFormsSubmissions.end(), + bind1st( ptr_fun( bindXFormsSubmission ), + rImport.GetModel() ) ); +} + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/layerimport.hxx b/xmloff/source/forms/layerimport.hxx new file mode 100644 index 000000000000..bd88a67975fd --- /dev/null +++ b/xmloff/source/forms/layerimport.hxx @@ -0,0 +1,227 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_LAYERIMPORT_HXX_ +#define _XMLOFF_FORMS_LAYERIMPORT_HXX_ + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/form/XFormsSupplier2.hpp> +#include <vos/ref.hxx> +#include "formattributes.hxx" +#include "callbacks.hxx" +#include "eventimport.hxx" +#include <tools/ref.hxx> + +class SvXMLImport; +class SvXMLImportContext; +class XMLPropertyHandlerFactory; +class SvXMLImportPropertyMapper; +class XMLPropStyleContext; + +SV_DECL_REF( SvXMLStylesContext ) + // unfortunately, we can't put this into our namespace, as the macro expands to (amongst others) a forward + // declaration of the class name, which then would be in the namespace, too + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + class OAttribute2Property; + + //===================================================================== + //= ControlReference + //===================================================================== + /// a structure containing a property set (the referred control) and a string (the list of referring controls) +/* struct ControlReference + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + xReferredControl; + ::rtl::OUString + sReferringControls; + + ControlReference( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxReferredControl, + const ::rtl::OUString& _rReferringControls) + :xReferredControl(_rxReferredControl) + ,sReferringControls(_rReferringControls) + { + } + }; +*/ + + //===================================================================== + //= OFormLayerXMLImport_Impl + //===================================================================== + class OFormLayerXMLImport_Impl + : public ODefaultEventAttacherManager + { + friend class OFormLayerXMLImport; + + protected: + SvXMLImport& m_rImporter; + OAttribute2Property m_aAttributeMetaData; + + /// the supplier for the forms of the currently imported page + ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormsSupplier2 > + m_xCurrentPageFormsSupp; + SvXMLStylesContext* m_pAutoStyles; + + protected: + // style handling + ::vos::ORef< XMLPropertyHandlerFactory > m_xPropertyHandlerFactory; + ::vos::ORef< SvXMLImportPropertyMapper > m_xImportMapper; + + DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >, MapString2PropertySet ); + DECLARE_STL_MAP( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >, MapString2PropertySet, ODrawPageCompare, MapDrawPage2Map); + + MapDrawPage2Map m_aControlIds; // ids of the controls on all known page + MapDrawPage2MapIterator m_aCurrentPageIds; // ifs of the controls on the current page + + typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >, ::rtl::OUString > + ModelStringPair; + ::std::vector< ModelStringPair > + m_aControlReferences; // control reference descriptions for current page + ::std::vector< ModelStringPair > + m_aCellValueBindings; // information about controls bound to spreadsheet cells + ::std::vector< ModelStringPair > + m_aCellRangeListSources;// information about controls bound to spreadsheet cell range list sources + + ::std::vector< ModelStringPair > + m_aXFormsValueBindings; // collect xforms:bind attributes to be resolved + + ::std::vector< ModelStringPair > + m_aXFormsListBindings; // collect forms:xforms-list-source attributes to be resolved + + ::std::vector< ModelStringPair > + m_aXFormsSubmissions; // collect xforms:submission attributes to be resolved + + public: + // IControlIdMap + void registerControlId( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl, + const ::rtl::OUString& _rId); + void registerControlReferences( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControl, + const ::rtl::OUString& _rReferringControls); + + // OFormLayerXMLImport_Impl + inline OAttribute2Property& getAttributeMap() { return m_aAttributeMetaData; } + inline SvXMLImport& getGlobalContext() { return m_rImporter; } + const SvXMLStyleContext* getStyleElement(const ::rtl::OUString& _rStyleName) const; + void enterEventContext(); + void leaveEventContext(); + void applyControlNumberStyle( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rControlNumerStyleName + ); + void registerCellValueBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rCellAddress + ); + + void registerCellRangeListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rCellRangeAddress + ); + + void registerXFormsValueBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rBindingID + ); + + void registerXFormsListBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rBindingID + ); + + void registerXFormsSubmission( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxControlModel, + const ::rtl::OUString& _rSubmissionID + ); + + protected: + OFormLayerXMLImport_Impl(SvXMLImport& _rImporter); + virtual ~OFormLayerXMLImport_Impl(); + + /** retrieves the property mapper form form related auto styles. + */ + ::vos::ORef< SvXMLImportPropertyMapper > getStylePropertyMapper() const; + + /** start importing the forms of the given page + */ + void startPage( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage); + + /** end importing the forms of the current page + */ + void endPage(); + + /** creates an import context for the office:forms element + */ + SvXMLImportContext* createOfficeFormsContext( + SvXMLImport& _rImport, + sal_uInt16 _nPrefix, + const rtl::OUString& _rLocalName); + + /** create an <type>SvXMLImportContext</type> instance which is able to import the <form:form> + element. + */ + SvXMLImportContext* createContext( + const sal_uInt16 _nPrefix, + const rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttribs); + + /** get the control with the given id + */ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + lookupControlId(const ::rtl::OUString& _rControlId); + + /** seek to the given page + */ + void seekPage( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& _rxDrawPage); + + /** announces the auto-style context to the form importer + */ + void setAutoStyleContext(SvXMLStylesContext* _pNewContext); + + /** to be called when the document has been completely imported + + <p>For some documents (currently: only some spreadsheet documents) it's necessary + do to a post processing, since not all information from the file can be processed + if the document is not completed, yet.</p> + */ + void documentDone( ); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_LAYERIMPORT_HXX_ + diff --git a/xmloff/source/forms/logging.cxx b/xmloff/source/forms/logging.cxx new file mode 100644 index 000000000000..25514ca20c5e --- /dev/null +++ b/xmloff/source/forms/logging.cxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "logging.hxx" +#include <rtl/logfile.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + +#ifdef TIMELOG + //===================================================================== + //= OStackedLogging + //===================================================================== + //--------------------------------------------------------------------- + void OStackedLogging::enterContext( const sal_Char* _pContextName ) + { + m_aLogger.push( new ::rtl::Logfile( _pContextName ) ); + } + + //--------------------------------------------------------------------- + void OStackedLogging::leaveTopContext( ) + { + delete m_aLogger.top(); + m_aLogger.pop(); + } +#endif + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/logging.hxx b/xmloff/source/forms/logging.hxx new file mode 100644 index 000000000000..332e00c3135e --- /dev/null +++ b/xmloff/source/forms/logging.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef XMLOFF_FORMS_LOGGING_HXX +#define XMLOFF_FORMS_LOGGING_HXX + +#include <sal/types.h> +#include <stack> + +namespace rtl { class Logfile; } + +//......................................................................... +namespace xmloff +{ +//......................................................................... + +#ifdef TIMELOG + + //===================================================================== + //= OStackedLogging + //===================================================================== + class OStackedLogging + { + private: + ::std::stack< ::rtl::Logfile* > m_aLogger; + + protected: + OStackedLogging() { } + + protected: + void enterContext( const sal_Char* _pContextName ); + void leaveTopContext( ); + }; + +#define ENTER_LOG_CONTEXT( name ) enterContext( name ) +#define LEAVE_LOG_CONTEXT( ) leaveTopContext( ) + +#else + struct OStackedLogging { }; + +#define ENTER_LOG_CONTEXT( name ) +#define LEAVE_LOG_CONTEXT( ) + +#endif + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // XMLOFF_FORMS_LOGGING_HXX + diff --git a/xmloff/source/forms/makefile.mk b/xmloff/source/forms/makefile.mk new file mode 100644 index 000000000000..8c46a4fbf3c9 --- /dev/null +++ b/xmloff/source/forms/makefile.mk @@ -0,0 +1,70 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=xmloff +TARGET=forms + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/officeforms.obj \ + $(SLO)$/formevents.obj \ + $(SLO)$/eventimport.obj \ + $(SLO)$/eventexport.obj \ + $(SLO)$/controlpropertyhdl.obj \ + $(SLO)$/controlpropertymap.obj \ + $(SLO)$/valueproperties.obj \ + $(SLO)$/attriblistmerge.obj \ + $(SLO)$/controlelement.obj \ + $(SLO)$/formlayerexport.obj \ + $(SLO)$/layerexport.obj \ + $(SLO)$/elementexport.obj \ + $(SLO)$/propertyexport.obj \ + $(SLO)$/elementimport.obj \ + $(SLO)$/layerimport.obj \ + $(SLO)$/propertyimport.obj \ + $(SLO)$/formlayerimport.obj \ + $(SLO)$/formattributes.obj \ + $(SLO)$/formenums.obj \ + $(SLO)$/formsimp.obj \ + $(SLO)$/strings.obj \ + $(SLO)$/logging.obj \ + $(SLO)$/formcellbinding.obj \ + $(SLO)$/gridcolumnproptranslator.obj \ + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/xmloff/source/forms/officeforms.cxx b/xmloff/source/forms/officeforms.cxx new file mode 100644 index 000000000000..d434d7a9addf --- /dev/null +++ b/xmloff/source/forms/officeforms.cxx @@ -0,0 +1,193 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "officeforms.hxx" +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmltoken.hxx> +#include "xmlnmspe.hxx" +#include <xmloff/xmlexp.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/nmspmap.hxx> +#include <comphelper/extract.hxx> +#include "strings.hxx" +#include <rtl/logfile.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::xml; + using ::xmloff::token::XML_FORMS; + + //========================================================================= + //= OFormsRootImport + //========================================================================= + TYPEINIT1(OFormsRootImport, SvXMLImportContext); + //------------------------------------------------------------------------- + OFormsRootImport::OFormsRootImport( SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLocalName ) + :SvXMLImportContext(rImport, nPrfx, rLocalName) + { + } + + //------------------------------------------------------------------------- + OFormsRootImport::~OFormsRootImport() + { + } + + //------------------------------------------------------------------------- + SvXMLImportContext* OFormsRootImport::CreateChildContext( USHORT _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList>& xAttrList ) + { + return GetImport().GetFormImport()->createContext( _nPrefix, _rLocalName, xAttrList ); + } + + //------------------------------------------------------------------------- + void OFormsRootImport::implImportBool(const Reference< sax::XAttributeList >& _rxAttributes, OfficeFormsAttributes _eAttribute, + const Reference< XPropertySet >& _rxProps, const Reference< XPropertySetInfo >& _rxPropInfo, + const ::rtl::OUString& _rPropName, sal_Bool _bDefault) + { + // the complete attribute name to look for + ::rtl::OUString sCompleteAttributeName = GetImport().GetNamespaceMap().GetQNameByIndex( + OAttributeMetaData::getOfficeFormsAttributeNamespace(_eAttribute), + ::rtl::OUString::createFromAscii(OAttributeMetaData::getOfficeFormsAttributeName(_eAttribute))); + + // get and convert the value + ::rtl::OUString sAttributeValue = _rxAttributes->getValueByName(sCompleteAttributeName); + sal_Bool bValue = _bDefault; + GetImport().GetMM100UnitConverter().convertBool(bValue, sAttributeValue); + + // set the property + if (_rxPropInfo->hasPropertyByName(_rPropName)) + _rxProps->setPropertyValue(_rPropName, ::cppu::bool2any(bValue)); + } + + //------------------------------------------------------------------------- + void OFormsRootImport::StartElement( const Reference< sax::XAttributeList >& _rxAttrList ) + { + ENTER_LOG_CONTEXT( "xmloff::OFormsRootImport - importing the complete tree" ); + SvXMLImportContext::StartElement( _rxAttrList ); + + try + { + Reference< XPropertySet > xDocProperties(GetImport().GetModel(), UNO_QUERY); + if ( xDocProperties.is() ) + { // an empty model is allowed: when doing a copy'n'paste from e.g. Writer to Calc, + // this is done via streaming the controls as XML. + Reference< XPropertySetInfo > xDocPropInfo; + if (xDocProperties.is()) + xDocPropInfo = xDocProperties->getPropertySetInfo(); + + implImportBool(_rxAttrList, ofaAutomaticFocus, xDocProperties, xDocPropInfo, PROPERTY_AUTOCONTROLFOCUS, sal_False); + implImportBool(_rxAttrList, ofaApplyDesignMode, xDocProperties, xDocPropInfo, PROPERTY_APPLYDESIGNMODE, sal_True); + } + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OFormsRootImport::StartElement: caught an exception while setting the document properties!"); + } + } + + //------------------------------------------------------------------------- + void OFormsRootImport::EndElement() + { + SvXMLImportContext::EndElement(); + LEAVE_LOG_CONTEXT( ); + } + + //===================================================================== + //= OFormsRootExport + //===================================================================== + //--------------------------------------------------------------------- + OFormsRootExport::OFormsRootExport( SvXMLExport& _rExp ) + :m_pImplElement(NULL) + { + addModelAttributes(_rExp); + + m_pImplElement = new SvXMLElementExport(_rExp, XML_NAMESPACE_OFFICE, XML_FORMS, sal_True, sal_True); + } + + //--------------------------------------------------------------------- + OFormsRootExport::~OFormsRootExport( ) + { + delete m_pImplElement; + } + + //------------------------------------------------------------------------- + void OFormsRootExport::implExportBool(SvXMLExport& _rExp, OfficeFormsAttributes _eAttribute, + const Reference< XPropertySet >& _rxProps, const Reference< XPropertySetInfo >& _rxPropInfo, + const ::rtl::OUString& _rPropName, sal_Bool _bDefault) + { + // retrieve the property value + sal_Bool bValue = _bDefault; + if (_rxPropInfo->hasPropertyByName(_rPropName)) + bValue = ::cppu::any2bool(_rxProps->getPropertyValue(_rPropName)); + + // convert into a string + ::rtl::OUStringBuffer aValue; + _rExp.GetMM100UnitConverter().convertBool(aValue, bValue); + + // add the attribute + _rExp.AddAttribute( + OAttributeMetaData::getOfficeFormsAttributeNamespace(_eAttribute), + OAttributeMetaData::getOfficeFormsAttributeName(_eAttribute), + aValue.makeStringAndClear()); + } + + //------------------------------------------------------------------------- + void OFormsRootExport::addModelAttributes(SvXMLExport& _rExp) SAL_THROW(()) + { + try + { + Reference< XPropertySet > xDocProperties(_rExp.GetModel(), UNO_QUERY); + if ( xDocProperties.is() ) + { // an empty model is allowed: when doing a copy'n'paste from e.g. Writer to Calc, + // this is done via streaming the controls as XML. + Reference< XPropertySetInfo > xDocPropInfo; + if (xDocProperties.is()) + xDocPropInfo = xDocProperties->getPropertySetInfo(); + + implExportBool(_rExp, ofaAutomaticFocus, xDocProperties, xDocPropInfo, PROPERTY_AUTOCONTROLFOCUS, sal_False); + implExportBool(_rExp, ofaApplyDesignMode, xDocProperties, xDocPropInfo, PROPERTY_APPLYDESIGNMODE, sal_True); + } + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OFormsRootExport::addModelAttributes: caught an exception while retrieving the document properties!"); + } + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/officeforms.hxx b/xmloff/source/forms/officeforms.hxx new file mode 100644 index 000000000000..2ca90197adb5 --- /dev/null +++ b/xmloff/source/forms/officeforms.hxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_OFFICEFORMS_HXX_ +#define _XMLOFF_FORMS_OFFICEFORMS_HXX_ + +#include "formattributes.hxx" +#include <xmloff/xmlictxt.hxx> +#include "logging.hxx" + +class SvXMLElementExport; +class SvXMLExport; + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OFormsRootImport + //===================================================================== + class OFormsRootImport + :public SvXMLImportContext + ,public OStackedLogging + { + public: + TYPEINFO(); + + OFormsRootImport( SvXMLImport& _rImport, sal_uInt16 _nPrfx, const rtl::OUString& _rLocalName); + virtual ~OFormsRootImport(); + + // SvXMLImportContext overriabled + virtual SvXMLImportContext * CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName, + const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList ); + virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList ); + virtual void EndElement(); + + protected: + void implImportBool( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttributes, + OfficeFormsAttributes _eAttribute, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxProps, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >& _rxPropInfo, + const ::rtl::OUString& _rPropName, + sal_Bool _bDefault + ); + }; + + //===================================================================== + //= OFormsRootExport + //===================================================================== + class OFormsRootExport + { + private: + SvXMLElementExport* m_pImplElement; + + public: + OFormsRootExport( SvXMLExport& _rExp ); + ~OFormsRootExport(); + + private: + void addModelAttributes(SvXMLExport& _rExp) SAL_THROW(()); + + void implExportBool( + SvXMLExport& _rExp, + OfficeFormsAttributes _eAttribute, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxProps, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >& _rxPropInfo, + const ::rtl::OUString& _rPropName, + sal_Bool _bDefault + ); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_OFFICEFORMS_HXX_ + + diff --git a/xmloff/source/forms/propertyexport.cxx b/xmloff/source/forms/propertyexport.cxx new file mode 100644 index 000000000000..1586c9a7a439 --- /dev/null +++ b/xmloff/source/forms/propertyexport.cxx @@ -0,0 +1,725 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include <stdio.h> +#include "propertyexport.hxx" +#include <xmloff/xmlexp.hxx> +#include "strings.hxx" +#include "xmlnmspe.hxx" +#include <xmloff/xmluconv.hxx> +#include <xmloff/families.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <osl/diagnose.h> +#include <comphelper/extract.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include "callbacks.hxx" +#include <unotools/datetime.hxx> +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <tools/datetime.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + + // NO using namespace ...util !!! + // need a tools Date/Time/DateTime below, which would conflict with the uno types then + + using namespace ::comphelper; + + //===================================================================== + //= OPropertyExport + //===================================================================== + //--------------------------------------------------------------------- + OPropertyExport::OPropertyExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxProps) + :m_rContext(_rContext) + ,m_xProps(_rxProps) + { + // caching + ::rtl::OUStringBuffer aBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertBool(aBuffer, sal_True); + m_sValueTrue = aBuffer.makeStringAndClear(); + m_rContext.getGlobalContext().GetMM100UnitConverter().convertBool(aBuffer, sal_False); + m_sValueFalse = aBuffer.makeStringAndClear(); + + m_xPropertyInfo = m_xProps->getPropertySetInfo(); + OSL_ENSURE(m_xPropertyInfo.is(), "OPropertyExport::OPropertyExport: need an XPropertySetInfo!"); + + // collect the properties which need to be exported + examinePersistence(); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportRemainingProperties() + { + // the properties tag (will be created if we have at least one no-default property) + SvXMLElementExport* pPropertiesTag = NULL; + + try + { + Reference< XPropertyState > xPropertyState( m_xProps, UNO_QUERY ); + Reference< XPropertySetInfo > xPSI( m_xProps->getPropertySetInfo() ); + + Any aValue; + ::rtl::OUString sValue; + + // loop through all the properties which are yet to be exported + for ( ConstStringSetIterator aProperty = m_aRemainingProps.begin(); + aProperty != m_aRemainingProps.end(); + ++aProperty + ) + { + DBG_CHECK_PROPERTY_NO_TYPE(*aProperty); + + #if OSL_DEBUG_LEVEL > 0 + const ::rtl::OUString sPropertyName = *aProperty; (void)sPropertyName; + #endif + // if the property state is DEFAULT, it does not need to be written - at least + // if it's a built-in property, and not a dynamically-added one. + bool bIsDefaultValue = xPropertyState.is() + && ( PropertyState_DEFAULT_VALUE == xPropertyState->getPropertyState( *aProperty ) ); + bool bIsDynamicProperty = xPSI.is() + && ( ( xPSI->getPropertyByName( *aProperty ).Attributes & PropertyAttribute::REMOVEABLE ) != 0 ); + if ( bIsDefaultValue && !bIsDynamicProperty ) + continue; + + // now that we have the first sub-tag we need the form:properties element + if (!pPropertiesTag) + pPropertiesTag = new SvXMLElementExport(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, token::XML_PROPERTIES, sal_True, sal_True); + + // add the name attribute + AddAttribute(XML_NAMESPACE_FORM, token::XML_PROPERTY_NAME, *aProperty); + + // get the value + aValue = m_xProps->getPropertyValue(*aProperty); + + // the type to export + Type aExportType; + + // is it a sequence + sal_Bool bIsSequence = TypeClass_SEQUENCE == aValue.getValueTypeClass(); + // the type of the property, maybe reduced to the element type of a sequence + if (bIsSequence) + aExportType = getSequenceElementType( aValue.getValueType() ); + else + aExportType = aValue.getValueType(); + + // the type attribute + // modified by BerryJia for Bug102407 + bool bIsEmptyValue = TypeClass_VOID == aValue.getValueType().getTypeClass(); + if ( bIsEmptyValue ) + { + com::sun::star::beans::Property aPropDesc; + aPropDesc = m_xPropertyInfo->getPropertyByName( *aProperty ); + aExportType = aPropDesc.Type; + } + token::XMLTokenEnum eValueType = implGetPropertyXMLType( aExportType ); + + if ( bIsEmptyValue ) + AddAttribute( XML_NAMESPACE_OFFICE, token::XML_VALUE_TYPE, token::XML_VOID ); + else + AddAttribute( XML_NAMESPACE_OFFICE, token::XML_VALUE_TYPE, eValueType ); + + token::XMLTokenEnum eValueAttName( token::XML_VALUE ); + switch ( eValueType ) + { + case token::XML_BOOLEAN: eValueAttName = token::XML_BOOLEAN_VALUE; break; + case token::XML_STRING: eValueAttName = token::XML_STRING_VALUE; break; + default: break; + } + + if( !bIsSequence && !bIsEmptyValue ) + { // the simple case + //add by BerryJia for Bug102407 + sValue = implConvertAny(aValue); + AddAttribute(XML_NAMESPACE_OFFICE, eValueAttName, sValue ); + } + + + // start the property tag + SvXMLElementExport aValueTag1(m_rContext.getGlobalContext(), + XML_NAMESPACE_FORM, + bIsSequence ? token::XML_LIST_PROPERTY + : token::XML_PROPERTY, sal_True, sal_True); + + if (!bIsSequence) + continue; + + // the not-that-simple case, we need to iterate through the sequence elements + IIterator* pSequenceIterator = NULL; + + switch ( aExportType.getTypeClass() ) + { + case TypeClass_STRING: + pSequenceIterator = new OSequenceIterator< ::rtl::OUString >(aValue); + break; + case TypeClass_DOUBLE: + pSequenceIterator = new OSequenceIterator< double >(aValue); + break; + case TypeClass_BOOLEAN: + pSequenceIterator = new OSequenceIterator< sal_Bool >(aValue); + break; + case TypeClass_BYTE: + pSequenceIterator = new OSequenceIterator< sal_Int8 >(aValue); + break; + case TypeClass_SHORT: + pSequenceIterator = new OSequenceIterator< sal_Int16 >(aValue); + break; + case TypeClass_LONG: + pSequenceIterator = new OSequenceIterator< sal_Int32 >(aValue); + break; + case TypeClass_HYPER: + pSequenceIterator = new OSequenceIterator< sal_Int64 >(aValue); + break; + default: + OSL_ENSURE(sal_False, "OPropertyExport::exportRemainingProperties: unsupported sequence tyoe !"); + break; + } + if (pSequenceIterator) + { + while (pSequenceIterator->hasMoreElements()) + { + sValue = + implConvertAny(pSequenceIterator->nextElement()); + AddAttribute(XML_NAMESPACE_OFFICE, eValueAttName, sValue ); + SvXMLElementExport aValueTag( + m_rContext.getGlobalContext(), + XML_NAMESPACE_FORM, token::XML_LIST_VALUE, + sal_True, sal_False); + } + } + delete pSequenceIterator; + } + } + catch(...) + { + delete pPropertiesTag; + throw; + } + delete pPropertiesTag; + } + + //--------------------------------------------------------------------- + void OPropertyExport::examinePersistence() + { + m_aRemainingProps.clear(); + Sequence< Property > aProperties = m_xPropertyInfo->getProperties(); + const Property* pProperties = aProperties.getConstArray(); + for (sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties) + { + // no transient props + if ( pProperties->Attributes & PropertyAttribute::TRANSIENT ) + continue; + // no read-only props + if ( ( pProperties->Attributes & PropertyAttribute::READONLY ) != 0 ) + // except they're dynamically added + if ( ( pProperties->Attributes & PropertyAttribute::REMOVEABLE ) == 0 ) + continue; + m_aRemainingProps.insert(pProperties->Name); + } + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportStringPropertyAttribute( const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName ) + { + DBG_CHECK_PROPERTY( _rPropertyName, ::rtl::OUString ); + + // no try-catch here, this would be to expensive. The outer scope has to handle exceptions (which should not + // happen if we're used correctly :) + + // this is way simple, as we don't need to convert anything (the property already is a string) + + // get the string + ::rtl::OUString sPropValue; + m_xProps->getPropertyValue( _rPropertyName ) >>= sPropValue; + + // add the attribute + if ( sPropValue.getLength() ) + AddAttribute( _nNamespaceKey, _pAttributeName, sPropValue ); + + // the property does not need to be handled anymore + exportedProperty( _rPropertyName ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportBooleanPropertyAttribute(const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, const sal_Int8 _nBooleanAttributeFlags) + { + DBG_CHECK_PROPERTY_NO_TYPE( _rPropertyName ); + // no check of the property value type: this method is allowed to be called with any interger properties + // (e.g. sal_Int32, sal_uInt16 etc) + + sal_Bool bDefault = (BOOLATTR_DEFAULT_TRUE == (BOOLATTR_DEFAULT_MASK & _nBooleanAttributeFlags)); + sal_Bool bDefaultVoid = (BOOLATTR_DEFAULT_VOID == (BOOLATTR_DEFAULT_MASK & _nBooleanAttributeFlags)); + + // get the value + sal_Bool bCurrentValue = bDefault; + Any aCurrentValue = m_xProps->getPropertyValue( _rPropertyName ); + if (aCurrentValue.hasValue()) + { + bCurrentValue = ::cppu::any2bool(aCurrentValue); + // this will extract a boolean value even if the Any contains a int or short or something like that ... + + if (_nBooleanAttributeFlags & BOOLATTR_INVERSE_SEMANTICS) + bCurrentValue = !bCurrentValue; + + // we have a non-void current value + if (bDefaultVoid || (bDefault != bCurrentValue)) + // and (the default is void, or the non-void default does not equal the current value) + // -> write the attribute + AddAttribute(_nNamespaceKey, _pAttributeName, bCurrentValue ? m_sValueTrue : m_sValueFalse); + } + else + // we have a void current value + if (!bDefaultVoid) + // and we have a non-void default + // -> write the attribute + AddAttribute(_nNamespaceKey, _pAttributeName, bCurrentValue ? m_sValueTrue : m_sValueFalse); + + // the property does not need to be handled anymore + exportedProperty( _rPropertyName ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportInt16PropertyAttribute(const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, const sal_Int16 _nDefault) + { + DBG_CHECK_PROPERTY( _rPropertyName, sal_Int16 ); + + // get the value + sal_Int16 nCurrentValue(_nDefault); + m_xProps->getPropertyValue( _rPropertyName ) >>= nCurrentValue; + + // add the attribute + if (_nDefault != nCurrentValue) + { + // let the formatter of the export context build a string + ::rtl::OUStringBuffer sBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(sBuffer, (sal_Int32)nCurrentValue); + + AddAttribute(_nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear()); + } + + // the property does not need to be handled anymore + exportedProperty( _rPropertyName ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportInt32PropertyAttribute( const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, const sal_Int32 _nDefault ) + { + DBG_CHECK_PROPERTY( _rPropertyName, sal_Int32 ); + + // get the value + sal_Int32 nCurrentValue( _nDefault ); + m_xProps->getPropertyValue( _rPropertyName ) >>= nCurrentValue; + + // add the attribute + if ( _nDefault != nCurrentValue ) + { + // let the formatter of the export context build a string + ::rtl::OUStringBuffer sBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber( sBuffer, nCurrentValue ); + + AddAttribute( _nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear() ); + } + + // the property does not need to be handled anymore + exportedProperty( _rPropertyName ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportEnumPropertyAttribute( + const sal_uInt16 _nNamespaceKey, const sal_Char* _pAttributeName, + const sal_Char* _pPropertyName, const SvXMLEnumMapEntry* _pValueMap, + const sal_Int32 _nDefault, const sal_Bool _bVoidDefault) + { + // get the value + sal_Int32 nCurrentValue(_nDefault); + ::rtl::OUString sPropertyName(::rtl::OUString::createFromAscii(_pPropertyName)); + Any aValue = m_xProps->getPropertyValue(sPropertyName); + + if (aValue.hasValue()) + { // we have a non-void current value + ::cppu::enum2int(nCurrentValue, aValue); + + // add the attribute + if ((_nDefault != nCurrentValue) || _bVoidDefault) + { // the default does not equal the value, or the default is void and the value isn't + + // let the formatter of the export context build a string + ::rtl::OUStringBuffer sBuffer; + m_rContext.getGlobalContext().GetMM100UnitConverter().convertEnum(sBuffer, (sal_uInt16)nCurrentValue, _pValueMap); + + AddAttribute(_nNamespaceKey, _pAttributeName, sBuffer.makeStringAndClear()); + } + } + else + { + if (!_bVoidDefault) + AddAttributeASCII(_nNamespaceKey, _pAttributeName, ""); + } + + // the property does not need to be handled anymore + exportedProperty(sPropertyName); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportTargetFrameAttribute() + { + DBG_CHECK_PROPERTY( PROPERTY_TARGETFRAME, ::rtl::OUString ); + + ::rtl::OUString sTargetFrame = comphelper::getString(m_xProps->getPropertyValue(PROPERTY_TARGETFRAME)); + if (0 != sTargetFrame.compareToAscii("_blank")) + { // an empty string and "_blank" have the same meaning and don't have to be written + AddAttribute(OAttributeMetaData::getCommonControlAttributeNamespace(CCA_TARGET_FRAME) + ,OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME) + ,sTargetFrame); + } + + exportedProperty(PROPERTY_TARGETFRAME); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportRelativeTargetLocation(const ConstAsciiString& _sPropertyName,sal_Int32 _nProperty) + { + DBG_CHECK_PROPERTY( _sPropertyName, ::rtl::OUString ); + + ::rtl::OUString sTargetLocation = comphelper::getString(m_xProps->getPropertyValue(_sPropertyName)); + if ( sTargetLocation.getLength() ) + // If this isn't a GraphicObject then GetRelativeReference + // will be called anyway ( in AddEmbeddedGraphic ) + sTargetLocation = m_rContext.getGlobalContext().AddEmbeddedGraphicObject(sTargetLocation); + AddAttribute(OAttributeMetaData::getCommonControlAttributeNamespace(_nProperty) + ,OAttributeMetaData::getCommonControlAttributeName(_nProperty) + , sTargetLocation); + + exportedProperty(_sPropertyName); + } + //--------------------------------------------------------------------- + void OPropertyExport::flagStyleProperties() + { + // flag all the properties which are part of the style as "handled" + UniReference< XMLPropertySetMapper > xStylePropertiesSupplier = m_rContext.getStylePropertyMapper()->getPropertySetMapper(); + for (sal_Int32 i=0; i<xStylePropertiesSupplier->GetEntryCount(); ++i) + exportedProperty(xStylePropertiesSupplier->GetEntryAPIName(i)); + + // the font properties are exported as single properties, but there is a FontDescriptor property which + // collects them all-in-one, this has been exported implicitly + exportedProperty(PROPERTY_FONT); + + // for the DateFormat and TimeFormat, there exist wrapper properties which has been exported as + // style, too + exportedProperty(PROPERTY_DATEFORMAT); + exportedProperty(PROPERTY_TIMEFORMAT); + + // the following properties should have been exported at the shape already: + exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VerticalAlign" ) ) ); + exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WritingMode" ) ) ); + exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScaleMode" ) ) ); + // ditto the TextWritingMode + exportedProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WritingMode" ) ) ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportGenericPropertyAttribute( + const sal_uInt16 _nAttributeNamespaceKey, const sal_Char* _pAttributeName, const sal_Char* _pPropertyName) + { + DBG_CHECK_PROPERTY_ASCII_NO_TYPE( _pPropertyName ); + + ::rtl::OUString sPropertyName = ::rtl::OUString::createFromAscii(_pPropertyName); + exportedProperty(sPropertyName); + + Any aCurrentValue = m_xProps->getPropertyValue(sPropertyName); + if (!aCurrentValue.hasValue()) + // nothing to do without a concrete value + return; + + ::rtl::OUString sValue = implConvertAny(aCurrentValue); + if (!sValue.getLength() && (TypeClass_STRING == aCurrentValue.getValueTypeClass())) + { + // check whether or not the property is allowed to be VOID + Property aProperty = m_xPropertyInfo->getPropertyByName(sPropertyName); + if ((aProperty.Attributes & PropertyAttribute::MAYBEVOID) == 0) + // the string is empty, and the property is not allowed to be void + // -> don't need to write the attibute, 'cause missing it is unambiguous + return; + } + + // finally add the attribuite to the context + AddAttribute(_nAttributeNamespaceKey, _pAttributeName, sValue); + } + + //--------------------------------------------------------------------- + void OPropertyExport::exportStringSequenceAttribute(const sal_uInt16 _nAttributeNamespaceKey, const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, + const sal_Unicode _aQuoteCharacter, const sal_Unicode _aListSeparator) + { + DBG_CHECK_PROPERTY( _rPropertyName, Sequence< ::rtl::OUString > ); + OSL_ENSURE(_aListSeparator != 0, "OPropertyExport::exportStringSequenceAttribute: invalid separator character!"); + + Sequence< ::rtl::OUString > aItems; + m_xProps->getPropertyValue( _rPropertyName ) >>= aItems; + + ::rtl::OUString sFinalList; + + // unfortunately the OUString can't append single sal_Unicode characters ... + const ::rtl::OUString sQuote(&_aQuoteCharacter, 1); + const ::rtl::OUString sSeparator(&_aListSeparator, 1); + const sal_Bool bQuote = 0 != sQuote.getLength(); + + // concatenate the string items + const ::rtl::OUString* pItems = aItems.getConstArray(); + const ::rtl::OUString* pEnd = pItems + aItems.getLength(); + const ::rtl::OUString* pLastElement = pEnd - 1; + for ( ; + pItems != pEnd; + ++pItems + ) + { + OSL_ENSURE(!_aQuoteCharacter || (-1 == pItems->indexOf(_aQuoteCharacter)), + "OPropertyExport::exportStringSequenceAttribute: there is an item which contains the quote character!"); + OSL_ENSURE(_aQuoteCharacter || (-1 == pItems->indexOf(_aListSeparator)), + "OPropertyExport::exportStringSequenceAttribute: no quote character, but there is an item containing the separator character!"); + + if (bQuote) + sFinalList += sQuote; + sFinalList += *pItems; + if (bQuote) + sFinalList += sQuote; + + if (pItems != pLastElement) + sFinalList += sSeparator; + } + + if (sFinalList.getLength()) + AddAttribute(_nAttributeNamespaceKey, _pAttributeName, sFinalList); + + exportedProperty( _rPropertyName ); + } + + //--------------------------------------------------------------------- + ::rtl::OUString OPropertyExport::implConvertAny(const Any& _rValue) + { + ::rtl::OUStringBuffer aBuffer; + switch (_rValue.getValueTypeClass()) + { + case TypeClass_STRING: + { // extract the string + ::rtl::OUString sCurrentValue; + _rValue >>= sCurrentValue; + aBuffer.append(sCurrentValue); + } + break; + case TypeClass_DOUBLE: + // let the unit converter format is as string + m_rContext.getGlobalContext().GetMM100UnitConverter().convertDouble(aBuffer, getDouble(_rValue)); + break; + case TypeClass_BOOLEAN: + aBuffer = getBOOL(_rValue) ? m_sValueTrue : m_sValueFalse; + break; + case TypeClass_BYTE: + case TypeClass_SHORT: + case TypeClass_LONG: + // let the unit converter format is as string + m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(aBuffer, getINT32(_rValue)); + break; + case TypeClass_HYPER: + // TODO + OSL_ENSURE(sal_False, "OPropertyExport::implConvertAny: missing implementation for sal_Int64!"); + break; + case TypeClass_ENUM: + { + // convert it into an int32 + sal_Int32 nValue = 0; + ::cppu::enum2int(nValue, _rValue); + m_rContext.getGlobalContext().GetMM100UnitConverter().convertNumber(aBuffer, nValue); + } + break; + default: + { // hmmm .... what else do we know? + double fValue = 0; + ::com::sun::star::util::Date aDate; + ::com::sun::star::util::Time aTime; + ::com::sun::star::util::DateTime aDateTime; + if (_rValue >>= aDate) + { + Date aToolsDate; + ::utl::typeConvert(aDate, aToolsDate); + fValue = aToolsDate.GetDate(); + } + else if (_rValue >>= aTime) + { + fValue = ((aTime.Hours * 60 + aTime.Minutes) * 60 + aTime.Seconds) * 100 + aTime.HundredthSeconds; + fValue = fValue / 8640000.0; + } + else if (_rValue >>= aDateTime) + { + DateTime aToolsDateTime; + ::utl::typeConvert(aDateTime, aToolsDateTime); + // the time part (the digits behind the comma) + fValue = ((aDateTime.Hours * 60 + aDateTime.Minutes) * 60 + aDateTime.Seconds) * 100 + aDateTime.HundredthSeconds; + fValue = fValue / 8640000.0; + // plus the data part (the digits in front of the comma) + fValue += aToolsDateTime.GetDate(); + } + else + { + // if any other types are added here, please remember to adjust implGetPropertyXMLType accordingly + + // no more options ... + OSL_ENSURE(sal_False, "OPropertyExport::implConvertAny: unsupported value type!"); + break; + } + // let the unit converter format is as string + m_rContext.getGlobalContext().GetMM100UnitConverter().convertDouble(aBuffer, fValue); + } + break; + } + + return aBuffer.makeStringAndClear(); + } + + + //--------------------------------------------------------------------- + token::XMLTokenEnum OPropertyExport::implGetPropertyXMLType(const ::com::sun::star::uno::Type& _rType) + { + // handle the type description + switch (_rType.getTypeClass()) + { + case TypeClass_STRING: + return token::XML_STRING; + case TypeClass_DOUBLE: + case TypeClass_BYTE: + case TypeClass_SHORT: + case TypeClass_LONG: + case TypeClass_HYPER: + case TypeClass_ENUM: + return token::XML_FLOAT; + case TypeClass_BOOLEAN: + return token::XML_BOOLEAN; + + default: + return token::XML_FLOAT; + } + } + +#ifdef DBG_UTIL + //--------------------------------------------------------------------- + void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, const sal_Char* _pName, const ::rtl::OUString& _rValue) + { + OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::rtl::OUString::createFromAscii(_pName)).getLength(), + "OPropertyExport::AddAttribute: already have such an attribute"); + + m_rContext.getGlobalContext().AddAttribute(_nPrefix, _pName, _rValue); + } + + //--------------------------------------------------------------------- + void OPropertyExport::AddAttribute( sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue ) + { + OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName( _rName ).getLength(), + "OPropertyExport::AddAttribute: already have such an attribute"); + + m_rContext.getGlobalContext().AddAttribute( _nPrefix, _rName, _rValue ); + } + + //--------------------------------------------------------------------- + void OPropertyExport::AddAttributeASCII(sal_uInt16 _nPrefix, const sal_Char* _pName, const sal_Char *pValue) + { + OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::rtl::OUString::createFromAscii(_pName)).getLength(), + "OPropertyExport::AddAttributeASCII: already have such an attribute"); + + m_rContext.getGlobalContext().AddAttributeASCII(_nPrefix, _pName, pValue); + } + + //--------------------------------------------------------------------- + void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, const ::rtl::OUString& _rValue) + { + OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::xmloff::token::GetXMLToken(_eName)).getLength(), + "OPropertyExport::AddAttribute: already have such an attribute"); + + m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _rValue); + } + + //--------------------------------------------------------------------- + void OPropertyExport::AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, ::xmloff::token::XMLTokenEnum _eValue ) + { + OSL_ENSURE(0 == m_rContext.getGlobalContext().GetXAttrList()->getValueByName(::xmloff::token::GetXMLToken(_eName)).getLength(), + "OPropertyExport::AddAttribute: already have such an attribute"); + + m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _eValue); + } + + //--------------------------------------------------------------------- + void OPropertyExport::dbg_implCheckProperty(const ::rtl::OUString& _rPropertyName, const Type* _pType) + { + try + { + // the property must exist + if (!m_xPropertyInfo->hasPropertyByName(_rPropertyName)) + { + OSL_ENSURE(sal_False, + ::rtl::OString("OPropertyExport::dbg_implCheckProperty: no property with the name ") += + ::rtl::OString(_rPropertyName.getStr(), _rPropertyName.getLength(), RTL_TEXTENCODING_ASCII_US) += + ::rtl::OString("!")); + return; + } + + if (_pType) + { + // and it must have the correct type + Property aPropertyDescription = m_xPropertyInfo->getPropertyByName(_rPropertyName); + OSL_ENSURE(aPropertyDescription.Type.equals(*_pType), "OPropertyExport::dbg_implCheckProperty: invalid property type!"); + } + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OPropertyExport::dbg_implCheckProperty: caught an exception, could not check the property!"); + } + } +#endif // DBG_UTIL - dbg_implCheckProperty + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/propertyexport.hxx b/xmloff/source/forms/propertyexport.hxx new file mode 100644 index 000000000000..5e1f683e339d --- /dev/null +++ b/xmloff/source/forms/propertyexport.hxx @@ -0,0 +1,408 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_PROPERTYEXPORT_HXX_ +#define _XMLOFF_FORMS_PROPERTYEXPORT_HXX_ + +#include "formattributes.hxx" +#include <comphelper/stl_types.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <callbacks.hxx> +#include <xmloff/xmlexp.hxx> +#include "callbacks.hxx" +#include "strings.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + +#define BOOLATTR_DEFAULT_FALSE 0x00 +#define BOOLATTR_DEFAULT_TRUE 0x01 +#define BOOLATTR_DEFAULT_VOID 0x02 +#define BOOLATTR_DEFAULT_MASK 0x03 + +#define BOOLATTR_INVERSE_SEMANTICS 0x04 + // if sal_True, indicates that the semantic of the property refered by <arg>_pPropertyName</arg> + // is inverse to the semantic of the XML attribute.<br/> + // I.e. if the property value is <TRUE/>, <FALSE/> has to be written and vice versa. + // <p>Be careful with <arg>_bDefault</arg> and <arg>_bInverseSemantics</arg>: if <arg>_bInverseSemantics</arg> + // is <TRUE/>, the current property value is inverted <em>before</em> comparing it to the default.</p> + + class IFormsExportContext; + //===================================================================== + //= OPropertyExport + //===================================================================== + /** provides export related tools for attribute handling + + <p>(The name is somewhat misleading. It's not only a PropertyExport, but in real a ElementExport. + Anyway.)</p> + */ + class OPropertyExport + { + private: + DECLARE_STL_STDKEY_SET(::rtl::OUString, StringSet); + StringSet m_aRemainingProps; + // see examinePersistence + + void exportRelativeTargetLocation(const ConstAsciiString& _sPropertyName,sal_Int32 _nProperty); + + protected: + IFormsExportContext& m_rContext; + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xProps; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > + m_xPropertyInfo; + + // caching + ::rtl::OUString m_sValueTrue; + ::rtl::OUString m_sValueFalse; + + public: + /** constructs an object capable of handling attributes for export + @param _rContext + the export context to which's attribute list the property translation should be added + @param m_xControl + the property set to be exported + */ + OPropertyExport(IFormsExportContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxProps); + + protected: + /** examines a property set given for all properties which's value are to made persistent + + <p>upon return the <method>m_aRemainingProps</method> will be filled with the names of all properties + which need to be stored</p> + */ + void examinePersistence(); + + /** + */ + void exportRemainingProperties(); + + /** indicates that a property has been handled by a derived class, without using the helper methods of this + class. + + <p>Calling this method is necessary in case you use the suggested mechanism for the generic export of + properties. This means that you want to use <method>exportRemainingProperties</method>, which exports + all properties which need to ('cause they haven't been exported with one of the other type-specific + methods).</p> + + <p>In this case you should call exportedProperty for every property you export yourself, so the property + will be flagged as <em>already handled</em></p> + */ + void exportedProperty(const ::rtl::OUString& _rPropertyName) + { m_aRemainingProps.erase(_rPropertyName); } + + /** add an attribute which is represented by a string property to the export context + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace + @param _pPropertyName + the name of the property to ask the control for + */ + void exportStringPropertyAttribute( + const sal_uInt16 _nNamespaceKey, + const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName + ); + + /** add an attribute which is represented by a boolean property to the export context + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the control for + @param _nBooleanAttributeFlags + specifies the default and the "alignment" (inverse semantics) of the boolean property + */ + void exportBooleanPropertyAttribute( + const sal_uInt16 _nNamespaceKey, + const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, + const sal_Int8 _nBooleanAttributeFlags); + + /** add an attribute which is represented by a sal_Int16 property to the export context + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the control for + @param _nDefault + the default of the attribute. If the current property value equals this default, no + attribute is added. + */ + void exportInt16PropertyAttribute( + const sal_uInt16 _nNamespaceKey, + const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, + const sal_Int16 _nDefault); + + /** add an attribute which is represented by a sal_Int32 property to the export context + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the control for + @param _nDefault + the default of the attribute. If the current property value equals this default, no + attribute is added. + */ + void exportInt32PropertyAttribute( + const sal_uInt16 _nNamespaceKey, + const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, + const sal_Int32 _nDefault); + + /** add an attribute which is represented by a enum property to the export context + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the control for + @param _pValueMap + the map to use when converting the property value to an attribute value + @param _nDefault + the default of the attribute. If the current property value equals this default, no + attribute is added. + */ + void exportEnumPropertyAttribute( + const sal_uInt16 _nNamespaceKey, + const sal_Char* _pAttributeName, + const sal_Char* _pPropertyName, + const SvXMLEnumMapEntry* _pValueMap, + const sal_Int32 _nDefault, + const sal_Bool _bVoidDefault = sal_False); + + // some very special methods for some very special attribute/property pairs + + /** add the hlink:target-frame attribute to the export context. + + <p>The value of this attribute is extracted from the TargetFrame property of the object given.</p> + + <p>The property needs a special handling because conflicts between the default values for the attribute + and the property.</p> + */ + void exportTargetFrameAttribute(); + + /** add the form:href attribute to the export context. + + <p>The value of this attribute is extracted from the TargetURL property of the object given.</p> + + <p>The property needs a special handling because the URL's need to be made relative</p> + */ + inline void exportTargetLocationAttribute() { exportRelativeTargetLocation(PROPERTY_TARGETURL,CCA_TARGET_LOCATION); } + + /** add the form:image attribute to the export context. + + <p>The value of this attribute is extracted from the ImageURL property of the object given.</p> + + <p>The property needs a special handling because the URL's need to be made relative</p> + */ + inline void exportImageDataAttribute() { exportRelativeTargetLocation(PROPERTY_IMAGEURL,CCA_IMAGE_DATA); } + + /** flag the style properties as 'already exported' + + <p>We don't have style support right now, so the only thing the method does is removing the style-relevant + properties from the list of yet-to-be-exported properties (<member>m_aRemainingProps</member>)</p> + */ + void flagStyleProperties(); + + /** add an arbitrary attribute extracted from an arbitrary property to the export context + + <p>The current value of the property specified wiht <arg>_pPropertyName</arg> is taken and converted + into a string, no matter what type it has. (Okay, there are the usual limitations: We know Date, Datetime, + double, integer ... to name just a few).</p> + + <p>In case the property value is <NULL/> (void), no attribute is added</p> + + <p>In case the property value is an empty string, and the property is a not allowed to be <NULL/> (void), + no attribute is added</p> + + <p>In case the property value is a sequence of any type, no attribute is added, 'cause sequences can't be + transported as attribute. In the debug version, an additional assertion will occur if you nonetheless try + to do this.</p> + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the object for + */ + void exportGenericPropertyAttribute( + const sal_uInt16 _nAttributeNamespaceKey, + const sal_Char* _pAttributeName, + const sal_Char* _pPropertyName); + + /** exports a property value, which is a string sequence, as attribute + + <p>The elements of the string sequence given are quoted and concatenated, with the characters used for + this to be choosen by the caller</p> + + <p>If you use the quote character, no check (except assertions) is made if one of the list items + containes the quote character</p> + + <p>If you don't use the quote character, no check (except assertions) is made if one of the list items + containes the separator character (which would be deadly when reimporting the string)</p> + + @param _nNamespaceKey + the key of the namespace to use for the attribute name. Is used with the namespace map + provided by the export context. + @param _pAttributeName + the name of the attribute to add. Must not contain any namespace (it's added automatically) + @param _pPropertyName + the name of the property to ask the object for + @param _aQuoteCharacter + the character to use to quote the sequence elements with. May be 0, in this case no quoting happens + @param _aListSeparator + the character to use to separate the list entries + */ + void exportStringSequenceAttribute( + const sal_uInt16 _nAttributeNamespaceKey, + const sal_Char* _pAttributeName, + const ::rtl::OUString& _rPropertyName, + const sal_Unicode _aQuoteCharacter = '"', + const sal_Unicode _aListSeparator = ','); + + /** tries to convert an arbitrary <type scope="com.sun:star.uno">Any</type> into an string + + <p>If the type contained in the Any is not supported, the returned string will be empty. In the + debug version, an additional assertion occurs.</p> + + @param _rValue + the value to convert + */ + ::rtl::OUString implConvertAny( + const ::com::sun::star::uno::Any& _rValue); + + /** + @return + token which can be used in the <code>form:property</code> element's <code>type</code> attribute + to describe the type of a value.<br/> + Possible types returned are + <ul> + <li><b>boolean</b>: <arg>_rValue</arg> was interpreted as boolean value before converting + it into a string</li> + <li><b>float</b>: <arg>_rValue</arg> was interpreted as 64 bit floating point 16bit integer, 32bit integer or 64 bit integer value before + converting it into a string</li> + <li><b>string</b>: <arg>_rValue</arg> did not need any conversion as it already was a string</li> + </ul> + If the type is not convertable, float is returned + */ + ::xmloff::token::XMLTokenEnum implGetPropertyXMLType(const ::com::sun::star::uno::Type& _rType); + +#ifdef DBG_UTIL + void AddAttribute(sal_uInt16 _nPrefix, const sal_Char* _pName, const ::rtl::OUString& _rValue); + void AddAttribute( sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue ); + void AddAttributeASCII( sal_uInt16 nPrefix, const sal_Char *pName, const sal_Char *pValue ); + void AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, const ::rtl::OUString& _rValue); + void AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, ::xmloff::token::XMLTokenEnum _eValue ); +#else + // in the product version, inline this, so it does not cost us extra time calling into our method + inline void AddAttribute(sal_uInt16 _nPrefix, const sal_Char* _pName, const ::rtl::OUString& _rValue) + { m_rContext.getGlobalContext().AddAttribute(_nPrefix, _pName, _rValue); } + inline void AddAttribute( sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue ) + { m_rContext.getGlobalContext().AddAttribute( _nPrefix, _rName, _rValue ); } + inline void AddAttributeASCII( sal_uInt16 _nPrefix, const sal_Char* _pName, const sal_Char *pValue ) + { m_rContext.getGlobalContext().AddAttributeASCII(_nPrefix, _pName, pValue); } + inline void AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, const ::rtl::OUString& _rValue) + { m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _rValue); } + inline void AddAttribute(sal_uInt16 _nPrefix, ::xmloff::token::XMLTokenEnum _eName, ::xmloff::token::XMLTokenEnum _eValue ) + { m_rContext.getGlobalContext().AddAttribute(_nPrefix, _eName, _eValue); } +#endif + +#ifdef DBG_UTIL + protected: + /** check a given property set for the existence and type correctness of a given property + + <p>This method is available in the non-product version only.</p> + + @param _rPropertyName + the name of the property to ask the control model for + @param _pType + the expected type of the property. May be NULL, in this case no type check is made. + @return sal_True, if the property exists and is of the correct type + */ + void dbg_implCheckProperty( + const ::rtl::OUString& _rPropertyName, + const ::com::sun::star::uno::Type* _pType); + +// void dbg_implCheckProperty( +// const sal_Char* _rPropertyName, +// const ::com::sun::star::uno::Type* _pType) +// { +// dbg_implCheckProperty(::rtl::OUString::createFromAscii(_rPropertyName), _pType); +// } +#endif + }; + + //===================================================================== + //= helper + //===================================================================== +#ifdef DBG_UTIL + #define DBG_CHECK_PROPERTY(name, type) \ + dbg_implCheckProperty(name, &::getCppuType(static_cast< type* >(NULL))) + + #define DBG_CHECK_PROPERTY_NO_TYPE(name) \ + dbg_implCheckProperty(name, NULL) + + #define DBG_CHECK_PROPERTY_ASCII( name, type ) \ + dbg_implCheckProperty( ::rtl::OUString::createFromAscii( name ), &::getCppuType(static_cast< type* >(NULL))) + + #define DBG_CHECK_PROPERTY_ASCII_NO_TYPE( name ) \ + dbg_implCheckProperty( ::rtl::OUString::createFromAscii( name ), NULL ) +#else + #define DBG_CHECK_PROPERTY(name, type) + #define DBG_CHECK_PROPERTY_NO_TYPE(name) + #define DBG_CHECK_PROPERTY_ASCII_NO_TYPE( name ) +#endif + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_PROPERTYEXPORT_HXX_ + + diff --git a/xmloff/source/forms/propertyimport.cxx b/xmloff/source/forms/propertyimport.cxx new file mode 100644 index 000000000000..597798f01ce7 --- /dev/null +++ b/xmloff/source/forms/propertyimport.cxx @@ -0,0 +1,641 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "propertyimport.hxx" +#include <xmloff/xmlimp.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/nmspmap.hxx> +#include <osl/diagnose.h> +#include <comphelper/extract.hxx> +#include "callbacks.hxx" +#include "xmlnmspe.hxx" +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <tools/datetime.hxx> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <unotools/datetime.hxx> +#include <rtl/logfile.hxx> + +#if OSL_DEBUG_LEVEL > 0 + #ifndef _OSL_THREAD_H_ + #include <osl/thread.h> + #endif +#endif + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::xml; + + // NO using namespace ...util !!! + // need a tools Date/Time/DateTime below, which would conflict with the uno types then + +#define TYPE_DATE 1 +#define TYPE_TIME 2 +#define TYPE_DATETIME 3 + +//===================================================================== +//= PropertyConversion +//===================================================================== +namespace +{ + //--------------------------------------------------------------------- + ::com::sun::star::util::Time lcl_getTime(double _nValue) + { + ::com::sun::star::util::Time aTime; + sal_uInt32 nIntValue = sal_Int32(_nValue * 8640000); + nIntValue *= 8640000; + aTime.HundredthSeconds = (sal_uInt16)( nIntValue % 100 ); + nIntValue /= 100; + aTime.Seconds = (sal_uInt16)( nIntValue % 60 ); + nIntValue /= 60; + aTime.Minutes = (sal_uInt16)( nIntValue % 60 ); + nIntValue /= 60; + OSL_ENSURE(nIntValue < 24, "lcl_getTime: more than a day?"); + aTime.Hours = static_cast< sal_uInt16 >( nIntValue ); + + return aTime; + } + + //--------------------------------------------------------------------- + static ::com::sun::star::util::Date lcl_getDate( double _nValue ) + { + Date aToolsDate((sal_uInt32)_nValue); + ::com::sun::star::util::Date aDate; + ::utl::typeConvert(aToolsDate, aDate); + return aDate; + } +} + +//--------------------------------------------------------------------- +Any PropertyConversion::convertString( SvXMLImport& _rImporter, const ::com::sun::star::uno::Type& _rExpectedType, + const ::rtl::OUString& _rReadCharacters, const SvXMLEnumMapEntry* _pEnumMap, const sal_Bool _bInvertBoolean ) +{ + Any aReturn; + sal_Bool bEnumAsInt = sal_False; + switch (_rExpectedType.getTypeClass()) + { + case TypeClass_BOOLEAN: // sal_Bool + { + sal_Bool bValue; + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rImporter.GetMM100UnitConverter().convertBool(bValue, _rReadCharacters); + OSL_ENSURE(bSuccess, + ::rtl::OString("PropertyConversion::convertString: could not convert \"") + += ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\" into a boolean!")); + aReturn = ::cppu::bool2any(_bInvertBoolean ? !bValue : bValue); + } + break; + case TypeClass_SHORT: // sal_Int16 + case TypeClass_LONG: // sal_Int32 + if (!_pEnumMap) + { // it's a real int32/16 property + sal_Int32 nValue(0); + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rImporter.GetMM100UnitConverter().convertNumber(nValue, _rReadCharacters); + OSL_ENSURE(bSuccess, + ::rtl::OString("PropertyConversion::convertString: could not convert \"") + += ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\" into an integer!")); + if (TypeClass_SHORT == _rExpectedType.getTypeClass()) + aReturn <<= (sal_Int16)nValue; + else + aReturn <<= (sal_Int32)nValue; + break; + } + bEnumAsInt = sal_True; + // NO BREAK! handle it as enum + case TypeClass_ENUM: + { + sal_uInt16 nEnumValue(0); + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rImporter.GetMM100UnitConverter().convertEnum(nEnumValue, _rReadCharacters, _pEnumMap); + OSL_ENSURE(bSuccess, "PropertyConversion::convertString: could not convert to an enum value!"); + if (bEnumAsInt) + if (TypeClass_SHORT == _rExpectedType.getTypeClass()) + aReturn <<= (sal_Int16)nEnumValue; + else + aReturn <<= (sal_Int32)nEnumValue; + else + aReturn = ::cppu::int2enum((sal_Int32)nEnumValue, _rExpectedType); + } + break; + case TypeClass_HYPER: + { + OSL_ENSURE(sal_False, "PropertyConversion::convertString: 64-bit integers not implemented yet!"); + } + break; + case TypeClass_DOUBLE: + { + double nValue; + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters); + OSL_ENSURE(bSuccess, + ::rtl::OString("PropertyConversion::convertString: could not convert \"") + += ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\" into a double!")); + aReturn <<= (double)nValue; + } + break; + case TypeClass_STRING: + aReturn <<= _rReadCharacters; + break; + case TypeClass_STRUCT: + { + sal_Int32 nType = 0; + if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::Date >::get() ) ) + nType = TYPE_DATE; + else if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::Time >::get() ) ) + nType = TYPE_TIME; + else if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::DateTime >::get() ) ) + nType = TYPE_DATETIME; + + if ( nType ) + { + // first extract the double + double nValue = 0; + #if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = + #endif + _rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters); + OSL_ENSURE(bSuccess, + ::rtl::OString("PropertyConversion::convertString: could not convert \"") + += ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\" into a double!")); + + // then convert it into the target type + switch (nType) + { + case TYPE_DATE: + { + OSL_ENSURE(((sal_uInt32)nValue) - nValue == 0, + "PropertyConversion::convertString: a Date value with a fractional part?"); + aReturn <<= lcl_getDate(nValue); + } + break; + case TYPE_TIME: + { + OSL_ENSURE(((sal_uInt32)nValue) == 0, + "PropertyConversion::convertString: a Time value with more than a fractional part?"); + aReturn <<= lcl_getTime(nValue); + } + break; + case TYPE_DATETIME: + { + ::com::sun::star::util::Time aTime = lcl_getTime(nValue); + ::com::sun::star::util::Date aDate = lcl_getDate(nValue); + + ::com::sun::star::util::DateTime aDateTime; + aDateTime.HundredthSeconds = aTime.HundredthSeconds; + aDateTime.Seconds = aTime.Seconds; + aDateTime.Minutes = aTime.Minutes; + aDateTime.Hours = aTime.Hours; + aDateTime.Day = aDate.Day; + aDateTime.Month = aDate.Month; + aDateTime.Year = aDate.Year; + aReturn <<= aDateTime; + } + break; + } + } + else + OSL_ENSURE(sal_False, "PropertyConversion::convertString: unsupported property type!"); + } + break; + default: + OSL_ENSURE(sal_False, "PropertyConversion::convertString: invalid type class!"); + } + + return aReturn; +} + +//--------------------------------------------------------------------- +Type PropertyConversion::xmlTypeToUnoType( const ::rtl::OUString& _rType ) +{ + Type aUnoType( ::getVoidCppuType() ); + + DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Type, MapString2Type ); + static MapString2Type s_aTypeNameMap; + if ( s_aTypeNameMap.empty() ) + { + s_aTypeNameMap[ token::GetXMLToken( token::XML_BOOLEAN ) ] = ::getBooleanCppuType(); + s_aTypeNameMap[ token::GetXMLToken( token::XML_FLOAT ) ] = ::getCppuType( static_cast< double* >(NULL) ); + s_aTypeNameMap[ token::GetXMLToken( token::XML_STRING ) ] = ::getCppuType( static_cast< ::rtl::OUString* >(NULL) ); + s_aTypeNameMap[ token::GetXMLToken( token::XML_VOID ) ] = ::getVoidCppuType(); + } + + const ConstMapString2TypeIterator aTypePos = s_aTypeNameMap.find( _rType ); + OSL_ENSURE( s_aTypeNameMap.end() != aTypePos, "PropertyConversion::xmlTypeToUnoType: invalid property name!" ); + if ( s_aTypeNameMap.end() != aTypePos ) + aUnoType = aTypePos->second; + + return aUnoType; +} + +//===================================================================== +//= OPropertyImport +//===================================================================== +//--------------------------------------------------------------------- +OPropertyImport::OPropertyImport(OFormLayerXMLImport_Impl& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName) + :SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName) + ,m_rContext(_rImport) + ,m_bTrackAttributes(sal_False) +{ +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OPropertyImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >& _rxAttrList) +{ + if( token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) ) + { + return new OPropertyElementsContext( m_rContext.getGlobalContext(), + _nPrefix, _rLocalName, this); + } + else + { + OSL_ENSURE(sal_False, + ::rtl::OString("OPropertyImport::CreateChildContext: unknown sub element (only \"properties\" is recognized, but it is ") + += ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString(")!")); + return SvXMLImportContext::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); + } +} + +//--------------------------------------------------------------------- +void OPropertyImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) +{ + OSL_ENSURE(_rxAttrList.is(), "OPropertyImport::StartElement: invalid attribute list!"); + const sal_Int32 nAttributeCount = _rxAttrList->getLength(); + + // assume the 'worst' case: all attributes describe properties. This should save our property array + // some reallocs + m_aValues.reserve(nAttributeCount); + + const SvXMLNamespaceMap& rMap = m_rContext.getGlobalContext().GetNamespaceMap(); + sal_uInt16 nNamespace; + ::rtl::OUString sLocalName; + for (sal_Int16 i=0; i<nAttributeCount; ++i) + { + nNamespace = rMap.GetKeyByAttrName(_rxAttrList->getNameByIndex(i), &sLocalName); + handleAttribute(nNamespace, sLocalName, _rxAttrList->getValueByIndex(i)); + + if (m_bTrackAttributes) + m_aEncounteredAttributes.insert(sLocalName); + } + + // TODO: create PropertyValues for all the attributes which were not present, because they were implied + // this is necessary as soon as we have properties where the XML default is different from the property + // default +} + +//--------------------------------------------------------------------- +sal_Bool OPropertyImport::encounteredAttribute(const ::rtl::OUString& _rAttributeName) const +{ + OSL_ENSURE(m_bTrackAttributes, "OPropertyImport::encounteredAttribute: attribute tracking not enabled!"); + return m_aEncounteredAttributes.end() != m_aEncounteredAttributes.find(_rAttributeName); +} + +//--------------------------------------------------------------------- +void OPropertyImport::Characters(const ::rtl::OUString& +#if OSL_DEBUG_LEVEL > 0 +_rChars +#endif +) +{ + // ignore them (should be whitespaces only) + OSL_ENSURE(0 == _rChars.trim().getLength(), "OPropertyImport::Characters: non-whitespace characters!"); +} + +//--------------------------------------------------------------------- +void OPropertyImport::handleAttribute(sal_uInt16 /*_nNamespaceKey*/, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue) +{ + const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName); + if (pProperty) + { + // create and store a new PropertyValue + PropertyValue aNewValue; + aNewValue.Name = pProperty->sPropertyName; + + // convert the value string into the target type + aNewValue.Value = PropertyConversion::convertString(m_rContext.getGlobalContext(), pProperty->aPropertyType, _rValue, pProperty->pEnumMap, pProperty->bInverseSemantics); + implPushBackPropertyValue( aNewValue ); + } +#if OSL_DEBUG_LEVEL > 0 + else + { + ::rtl::OString sMessage( "OPropertyImport::handleAttribute: Can't handle the following:\n" ); + sMessage += ::rtl::OString( " Attribute name: " ); + sMessage += ::rtl::OString( _rLocalName.getStr(), _rLocalName.getLength(), osl_getThreadTextEncoding() ); + sMessage += ::rtl::OString( "\n value: " ); + sMessage += ::rtl::OString( _rValue.getStr(), _rValue.getLength(), osl_getThreadTextEncoding() ); + OSL_ENSURE( sal_False, sMessage.getStr() ); + } +#endif +} + +//===================================================================== +//= OPropertyElementsContext +//===================================================================== +//--------------------------------------------------------------------- +OPropertyElementsContext::OPropertyElementsContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter) + :SvXMLImportContext(_rImport, _nPrefix, _rName) + ,m_xPropertyImporter(_rPropertyImporter) +{ +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OPropertyElementsContext::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >&) +{ + if( token::IsXMLToken( _rLocalName, token::XML_PROPERTY ) ) + { + return new OSinglePropertyContext(GetImport(), _nPrefix, _rLocalName, m_xPropertyImporter); + } + else if( token::IsXMLToken( _rLocalName, token::XML_LIST_PROPERTY ) ) + { + return new OListPropertyContext( GetImport(), _nPrefix, _rLocalName, m_xPropertyImporter ); + } + else + { + OSL_ENSURE(sal_False, + ::rtl::OString("OPropertyElementsContext::CreateChildContext: unknown child element (\"") + += ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\")!")); + return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName); + } +} + +#if OSL_DEBUG_LEVEL > 0 + //--------------------------------------------------------------------- + void OPropertyElementsContext::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) + { + OSL_ENSURE(0 == _rxAttrList->getLength(), "OPropertyElementsContext::StartElement: the form:properties element should not have attributes!"); + SvXMLImportContext::StartElement(_rxAttrList); + } + + //--------------------------------------------------------------------- + void OPropertyElementsContext::Characters(const ::rtl::OUString& _rChars) + { + OSL_ENSURE(0 == _rChars.trim(), "OPropertyElementsContext::Characters: non-whitespace characters detected!"); + SvXMLImportContext::Characters(_rChars); + } + +#endif + +//===================================================================== +//= OSinglePropertyContext +//===================================================================== +//--------------------------------------------------------------------- +OSinglePropertyContext::OSinglePropertyContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter) + :SvXMLImportContext(_rImport, _nPrefix, _rName) + ,m_xPropertyImporter(_rPropertyImporter) +{ +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OSinglePropertyContext::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const Reference< sax::XAttributeList >&) +{ + OSL_ENSURE(sal_False, + ::rtl::OString("OSinglePropertyContext::CreateChildContext: unknown child element (\"") + += ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\")!")); + return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName); +} + +//--------------------------------------------------------------------- +void OSinglePropertyContext::StartElement(const Reference< sax::XAttributeList >& _rxAttrList) +{ + ::com::sun::star::beans::PropertyValue aPropValue; // the property the instance imports currently + ::com::sun::star::uno::Type aPropType; // the type of the property the instance imports currently + + ::rtl::OUString sType, sValue; + const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap(); + const sal_Int16 nAttrCount = _rxAttrList.is() ? _rxAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const ::rtl::OUString& rAttrName = _rxAttrList->getNameByIndex( i ); + //const ::rtl::OUString& rValue = _rxAttrList->getValueByIndex( i ); + + ::rtl::OUString aLocalName; + sal_uInt16 nPrefix = + rMap.GetKeyByAttrName( rAttrName, + &aLocalName ); + if( XML_NAMESPACE_FORM == nPrefix ) + { + if( token::IsXMLToken( aLocalName, token::XML_PROPERTY_NAME ) ) + aPropValue.Name = _rxAttrList->getValueByIndex( i ); + + } + else if( XML_NAMESPACE_OFFICE == nPrefix ) + { + if( token::IsXMLToken( aLocalName, token::XML_VALUE_TYPE ) ) + sType = _rxAttrList->getValueByIndex( i ); + else if( token::IsXMLToken( aLocalName, + token::XML_VALUE ) || + token::IsXMLToken( aLocalName, + token::XML_BOOLEAN_VALUE ) || + token::IsXMLToken( aLocalName, + token::XML_STRING_VALUE ) ) + sValue = _rxAttrList->getValueByIndex( i ); + } + } + + // the name of the property + OSL_ENSURE(aPropValue.Name.getLength(), "OSinglePropertyContext::StartElement: invalid property name!"); + + // needs to be translated into a ::com::sun::star::uno::Type + aPropType = PropertyConversion::xmlTypeToUnoType( sType ); + if( TypeClass_VOID == aPropType.getTypeClass() ) + { + aPropValue.Value = Any(); + } + else + { + aPropValue.Value = + PropertyConversion::convertString(GetImport(), aPropType, + sValue); + } + + // now that we finally have our property value, add it to our parent object + if( aPropValue.Name.getLength() ) + m_xPropertyImporter->implPushBackGenericPropertyValue(aPropValue); +} + +//===================================================================== +//= OListPropertyContext +//===================================================================== +//--------------------------------------------------------------------- +OListPropertyContext::OListPropertyContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter ) + :SvXMLImportContext( _rImport, _nPrefix, _rName ) + ,m_xPropertyImporter( _rPropertyImporter ) +{ +} + +//--------------------------------------------------------------------- +void OListPropertyContext::StartElement( const Reference< sax::XAttributeList >& _rxAttrList ) +{ + sal_Int32 nAttributeCount = _rxAttrList->getLength(); + + sal_uInt16 nNamespace; + ::rtl::OUString sAttributeName; + const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap(); + for ( sal_Int16 i = 0; i < nAttributeCount; ++i ) + { + nNamespace = rMap.GetKeyByAttrName( _rxAttrList->getNameByIndex( i ), &sAttributeName ); + if ( ( XML_NAMESPACE_FORM == nNamespace ) + && ( token::IsXMLToken( sAttributeName, token::XML_PROPERTY_NAME ) ) + ) + { + m_sPropertyName = _rxAttrList->getValueByIndex( i ); + } + else if ( ( XML_NAMESPACE_OFFICE == nNamespace ) + && ( token::IsXMLToken( sAttributeName, token::XML_VALUE_TYPE ) ) + ) + { + m_sPropertyType = _rxAttrList->getValueByIndex( i ); + } + else + { + OSL_ENSURE( false, + ::rtl::OString( "OListPropertyContext::StartElement: unknown child element (\"") + += ::rtl::OString( sAttributeName.getStr(), sAttributeName.getLength(), RTL_TEXTENCODING_ASCII_US ) + += ::rtl::OString( "\")!" ) ); + } + } +} + +//--------------------------------------------------------------------- +void OListPropertyContext::EndElement() +{ + OSL_ENSURE( m_sPropertyName.getLength() && m_sPropertyType.getLength(), + "OListPropertyContext::EndElement: no property name or type!" ); + + if ( !m_sPropertyName.getLength() || !m_sPropertyType.getLength() ) + return; + + Sequence< Any > aListElements( m_aListValues.size() ); + Any* pListElement = aListElements.getArray(); + com::sun::star::uno::Type aType = PropertyConversion::xmlTypeToUnoType( m_sPropertyType ); + for ( ::std::vector< ::rtl::OUString >::const_iterator values = m_aListValues.begin(); + values != m_aListValues.end(); + ++values, ++pListElement + ) + { + *pListElement = PropertyConversion::convertString( GetImport(), aType, *values ); + } + + PropertyValue aSequenceValue; + aSequenceValue.Name = m_sPropertyName; + aSequenceValue.Value <<= aListElements; + + m_xPropertyImporter->implPushBackGenericPropertyValue( aSequenceValue ); +} + +//--------------------------------------------------------------------- +SvXMLImportContext* OListPropertyContext::CreateChildContext( sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, const Reference< sax::XAttributeList >& /*_rxAttrList*/ ) +{ + if ( token::IsXMLToken( _rLocalName, token::XML_LIST_VALUE ) ) + { + m_aListValues.resize( m_aListValues.size() + 1 ); + return new OListValueContext( GetImport(), _nPrefix, _rLocalName, *m_aListValues.rbegin() ); + } + else + { + OSL_ENSURE( sal_False, + ::rtl::OString("OListPropertyContext::CreateChildContext: unknown child element (\"") + += ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US) + += ::rtl::OString("\")!")); + return new SvXMLImportContext( GetImport(), _nPrefix, _rLocalName ); + } +} + +//===================================================================== +//= OListValueContext +//===================================================================== +//--------------------------------------------------------------------- +OListValueContext::OListValueContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, ::rtl::OUString& _rListValueHolder ) + :SvXMLImportContext( _rImport, _nPrefix, _rName ) + ,m_rListValueHolder( _rListValueHolder ) +{ +} + +//--------------------------------------------------------------------- +void OListValueContext::StartElement( const Reference< sax::XAttributeList >& _rxAttrList ) +{ + const sal_Int32 nAttributeCount = _rxAttrList->getLength(); + + sal_uInt16 nNamespace; + ::rtl::OUString sAttributeName; + const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap(); + for ( sal_Int16 i = 0; i < nAttributeCount; ++i ) + { + nNamespace = rMap.GetKeyByAttrName( _rxAttrList->getNameByIndex( i ), &sAttributeName ); + if ( XML_NAMESPACE_OFFICE == nNamespace ) + { + if ( token::IsXMLToken( sAttributeName, token::XML_VALUE ) + || token::IsXMLToken( sAttributeName, token::XML_STRING_VALUE ) + || token::IsXMLToken( sAttributeName, token::XML_BOOLEAN_VALUE ) + ) + { + m_rListValueHolder = _rxAttrList->getValueByIndex( i ); + continue; + } + } + + OSL_ENSURE( false, + ::rtl::OString( "OListValueContext::StartElement: unknown child element (\"") + += ::rtl::OString( sAttributeName.getStr(), sAttributeName.getLength(), RTL_TEXTENCODING_ASCII_US ) + += ::rtl::OString( "\")!" ) ); + } +} + +//......................................................................... +} // namespace xmloff +//......................................................................... + diff --git a/xmloff/source/forms/propertyimport.hxx b/xmloff/source/forms/propertyimport.hxx new file mode 100644 index 000000000000..30bc8bb1d617 --- /dev/null +++ b/xmloff/source/forms/propertyimport.hxx @@ -0,0 +1,253 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_PROPERTYIMPORT_HXX_ +#define _XMLOFF_FORMS_PROPERTYIMPORT_HXX_ + +#include <xmloff/xmlictxt.hxx> +#include "formattributes.hxx" +#include <vos/ref.hxx> +#include <comphelper/stl_types.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include "layerimport.hxx" + +namespace com { namespace sun { namespace star { namespace util { + struct Time; + struct Date; +} } } } + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= PropertyConversion + //===================================================================== + class PropertyConversion + { + public: + static ::com::sun::star::uno::Any convertString( + SvXMLImport& _rImporter, + const ::com::sun::star::uno::Type& _rExpectedType, + const ::rtl::OUString& _rReadCharacters, + const SvXMLEnumMapEntry* _pEnumMap = NULL, + const sal_Bool _bInvertBoolean = sal_False + ); + + static ::com::sun::star::uno::Type xmlTypeToUnoType( const ::rtl::OUString& _rType ); + }; + + class OFormLayerXMLImport_Impl; + //===================================================================== + //= OPropertyImport + //===================================================================== + /** Helper class for importing property values + + <p>This class imports properties which are stored as attributes as well as properties which + are stored in </em><form:properties></em> elements.</p> + */ + class OPropertyImport : public SvXMLImportContext + { + friend class OSinglePropertyContext; + friend class OListPropertyContext; + + protected: + typedef ::std::vector< ::com::sun::star::beans::PropertyValue > PropertyValueArray; + PropertyValueArray m_aValues; + PropertyValueArray m_aGenericValues; + // the values which the instance collects between StartElement and EndElement + + DECLARE_STL_STDKEY_SET( ::rtl::OUString, StringSet ); + StringSet m_aEncounteredAttributes; + + OFormLayerXMLImport_Impl& m_rContext; + + sal_Bool m_bTrackAttributes; + + // TODO: think about the restriction that the class does not know anything about the object it is importing. + // Perhaps this object should be known to the class, so setting the properties ('normal' ones as well as + // style properties) can be done in our own EndElement instead of letting derived classes do this. + + public: + OPropertyImport(OFormLayerXMLImport_Impl& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName); + + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void Characters(const ::rtl::OUString& _rChars); + + protected: + /** handle one single attribute. + + <p>This is called for every attribute of the element. This class' implementaion checks if the attribute + describes a property, if so, it is added to <member>m_aValues</member>.</p> + + <p>All non-property attributes should be handled in derived classes.</p> + + @param _nNamespaceKey + key of the namespace used in the attribute + @param _rLocalName + local (relative to the namespace) attribute name + @param _rValue + attribute value + */ + virtual void handleAttribute(sal_uInt16 _nNamespaceKey, + const ::rtl::OUString& _rLocalName, + const ::rtl::OUString& _rValue); + + /** determine if the element imported by the object had an given attribute. + <p>Please be aware of the fact that the name given must be a local name, i.e. not contain a namespace. + All form relevant attributes are in the same namespace, so this would be an redundant information.</p> + */ + sal_Bool encounteredAttribute(const ::rtl::OUString& _rAttributeName) const; + + /** determine if the element imported by the object had an given attribute. + <p>Please be aware of the fact that the name given must be a local name, i.e. not contain a namespace. + All form relevant attributes are in the same namespace, so this would be an redundant information.</p> + */ + sal_Bool encounteredAttribute(const sal_Char* _pAttributeName) const { return encounteredAttribute(::rtl::OUString::createFromAscii(_pAttributeName)); } + + /** enables the tracking of the encountered attributes + <p>The tracking will raise the import costs a little bit, but it's cheaper than + derived classes tracking this themself.</p> + */ + void enableTrackAttributes() { m_bTrackAttributes = sal_True; } + + inline void implPushBackPropertyValue(const ::com::sun::star::beans::PropertyValue& _rProp) + { + m_aValues.push_back(_rProp); + } + + inline void implPushBackPropertyValue( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Any& _rValue ) + { + m_aValues.push_back( ::com::sun::star::beans::PropertyValue( + _rName, -1, _rValue, ::com::sun::star::beans::PropertyState_DIRECT_VALUE ) ); + } + + inline void implPushBackGenericPropertyValue(const ::com::sun::star::beans::PropertyValue& _rProp) + { + m_aGenericValues.push_back(_rProp); + } + }; + SV_DECL_IMPL_REF( OPropertyImport ) + + //===================================================================== + //= OPropertyElementsContext + //===================================================================== + /** helper class for importing the <form:properties> element + */ + class OPropertyElementsContext : public SvXMLImportContext + { + protected: + OPropertyImportRef m_xPropertyImporter; // to add the properties + + public: + OPropertyElementsContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter); + + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + +#if OSL_DEBUG_LEVEL > 0 + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + virtual void Characters(const ::rtl::OUString& _rChars); +#endif + }; + + //===================================================================== + //= OSinglePropertyContext + //===================================================================== + /** helper class for importing a single <form:property> element + */ + class OSinglePropertyContext : public SvXMLImportContext + { + OPropertyImportRef m_xPropertyImporter; // to add the properties + + public: + OSinglePropertyContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter); + + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + }; + + //===================================================================== + //= OListPropertyContext + //===================================================================== + class OListPropertyContext : public SvXMLImportContext + { + OPropertyImportRef m_xPropertyImporter; + ::rtl::OUString m_sPropertyName; + ::rtl::OUString m_sPropertyType; + ::std::vector< ::rtl::OUString > m_aListValues; + + public: + OListPropertyContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + const OPropertyImportRef& _rPropertyImporter ); + + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList ); + + virtual void EndElement(); + + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList); + }; + + //===================================================================== + //= OListValueContext + //===================================================================== + class OListValueContext : public SvXMLImportContext + { + ::rtl::OUString& m_rListValueHolder; + + public: + OListValueContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, + ::rtl::OUString& _rListValueHolder ); + + virtual void StartElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& _rxAttrList ); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_PROPERTYIMPORT_HXX_ + + diff --git a/xmloff/source/forms/strings.cxx b/xmloff/source/forms/strings.cxx new file mode 100644 index 000000000000..33986212255e --- /dev/null +++ b/xmloff/source/forms/strings.cxx @@ -0,0 +1,37 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#ifndef _XMLOFF_FORMS_STRINGS_HXX_ +#define XMLFORM_IMPLEMENT_STRINGS +#include "strings.hxx" +#undef XMLFORM_IMPLEMENT_STRINGS +#endif + + diff --git a/xmloff/source/forms/strings.hxx b/xmloff/source/forms/strings.hxx new file mode 100644 index 000000000000..66a5f76786fe --- /dev/null +++ b/xmloff/source/forms/strings.hxx @@ -0,0 +1,283 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_STRINGS_HXX_ +#define _XMLOFF_FORMS_STRINGS_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //============================================================ + //= a helper for static ascii pseudo-unicode strings + //============================================================ + struct ConstAsciiString + { + const sal_Char* ascii; + sal_Int32 length; + + inline operator const ConstAsciiString* () const { return this; } + inline const ::rtl::OUString* operator& () const; + inline operator const ::rtl::OUString& () const { return *(&(*this)); } + inline operator const sal_Char* () const { return ascii; } + + inline ConstAsciiString(const sal_Char* _pAsciiZeroTerminated, const sal_Int32 _nLength); + inline ~ConstAsciiString(); + + private: + mutable ::rtl::OUString* m_pString; + + private: + ConstAsciiString(); // never implemented + }; + + //------------------------------------------------------------ + inline ConstAsciiString::ConstAsciiString(const sal_Char* _pAsciiZeroTerminated, const sal_Int32 _nLength) + :ascii( _pAsciiZeroTerminated ) + ,length( _nLength ) + ,m_pString( NULL ) + { + } + + //------------------------------------------------------------ + inline ConstAsciiString::~ConstAsciiString() + { + if ( m_pString ) + { + delete m_pString; + m_pString = NULL; + } + } + + //------------------------------------------------------------ + inline const ::rtl::OUString* ConstAsciiString::operator& () const + { + if ( !m_pString ) + m_pString = new ::rtl::OUString( ascii, length, RTL_TEXTENCODING_ASCII_US ); + return m_pString; + } + +#ifndef XMLFORM_IMPLEMENT_STRINGS + #define XMLFORM_CONSTASCII_STRING(ident, string) extern const ConstAsciiString ident +#else + #define XMLFORM_CONSTASCII_STRING(ident, string) extern const ConstAsciiString ident(string, sizeof(string)-1) +#endif + + //============================================================ + //= string constants + //============================================================ + + // properties + XMLFORM_CONSTASCII_STRING( PROPERTY_CLASSID, "ClassId" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ECHOCHAR, "EchoChar" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_MULTILINE, "MultiLine" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_NAME, "Name" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_IMAGEURL, "ImageURL" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_LABEL, "Label" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_TARGETFRAME, "TargetFrame" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_TARGETURL, "TargetURL" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_TITLE, "Tag" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_DROPDOWN, "Dropdown" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_PRINTABLE, "Printable" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_READONLY, "ReadOnly" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_STATE, "DefaultState" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_TABSTOP, "Tabstop" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_STATE, "State" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ENABLED, "Enabled" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ENABLEVISIBLE, "EnableVisible" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_MAXTEXTLENGTH, "MaxTextLen" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_LINECOUNT, "LineCount" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_TABINDEX, "TabIndex" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_COMMAND, "Command" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATASOURCENAME, "DataSourceName" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_FILTER, "Filter" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ORDER, "Order" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ALLOWDELETES, "AllowDeletes" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ALLOWINSERTS, "AllowInserts" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ALLOWUPDATES, "AllowUpdates" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_APPLYFILTER, "ApplyFilter" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_ESCAPEPROCESSING, "EscapeProcessing" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_IGNORERESULT, "IgnoreResult" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_SUBMIT_ENCODING, "SubmitEncoding" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_SUBMIT_METHOD, "SubmitMethod" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_COMMAND_TYPE, "CommandType" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_NAVIGATION, "NavigationBarMode" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_CYCLE, "Cycle" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_BUTTONTYPE, "ButtonType" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATAFIELD, "DataField" ); + XMLFORM_CONSTASCII_STRING( PROPERTY_BOUNDCOLUMN, "BoundColumn"); + XMLFORM_CONSTASCII_STRING( PROPERTY_EMPTY_IS_NULL, "ConvertEmptyToNull"); + XMLFORM_CONSTASCII_STRING( PROPERTY_INPUT_REQUIRED, "InputRequired"); + XMLFORM_CONSTASCII_STRING( PROPERTY_LISTSOURCE, "ListSource"); + XMLFORM_CONSTASCII_STRING( PROPERTY_LISTSOURCETYPE, "ListSourceType"); + XMLFORM_CONSTASCII_STRING( PROPERTY_ECHO_CHAR, "EchoChar"); + XMLFORM_CONSTASCII_STRING( PROPERTY_STRICTFORMAT, "StrictFormat"); + XMLFORM_CONSTASCII_STRING( PROPERTY_AUTOCOMPLETE, "Autocomplete"); + XMLFORM_CONSTASCII_STRING( PROPERTY_MULTISELECTION, "MultiSelection"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULTBUTTON, "DefaultButton"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TRISTATE, "TriState"); + XMLFORM_CONSTASCII_STRING( PROPERTY_CONTROLLABEL, "LabelControl"); + XMLFORM_CONSTASCII_STRING( PROPERTY_STRING_ITEM_LIST, "StringItemList"); + XMLFORM_CONSTASCII_STRING( PROPERTY_VALUE_SEQ, "ValueItemList"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_SELECT_SEQ, "DefaultSelection"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SELECT_SEQ, "SelectedItems"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATE_MIN, "DateMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATE_MAX, "DateMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TIME_MIN, "TimeMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TIME_MAX, "TimeMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_VALUE_MIN, "ValueMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_VALUE_MAX, "ValueMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_EFFECTIVE_MIN, "EffectiveMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_EFFECTIVE_MAX, "EffectiveMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_DATE, "DefaultDate"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATE, "Date"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_TIME, "DefaultTime"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TIME, "Time"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_VALUE, "DefaultValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_VALUE, "Value"); + XMLFORM_CONSTASCII_STRING( PROPERTY_HIDDEN_VALUE, "HiddenValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_TEXT, "DefaultText"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TEXT, "Text"); + XMLFORM_CONSTASCII_STRING( PROPERTY_EFFECTIVE_VALUE, "EffectiveValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_EFFECTIVE_DEFAULT, "EffectiveDefault"); + XMLFORM_CONSTASCII_STRING( PROPERTY_REFVALUE, "RefValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_URL, "URL"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FONT, "FontDescriptor"); + XMLFORM_CONSTASCII_STRING( PROPERTY_BACKGROUNDCOLOR, "BackgroundColor"); + XMLFORM_CONSTASCII_STRING( PROPERTY_MASTERFIELDS, "MasterFields"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DETAILFIELDS, "DetailFields"); + XMLFORM_CONSTASCII_STRING( PROPERTY_COLUMNSERVICENAME, "ColumnServiceName"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FORMATKEY, "FormatKey"); + XMLFORM_CONSTASCII_STRING( PROPERTY_ALIGN, "Align"); + XMLFORM_CONSTASCII_STRING( PROPERTY_BORDER, "Border"); + XMLFORM_CONSTASCII_STRING( PROPERTY_AUTOCONTROLFOCUS, "AutomaticControlFocus"); + XMLFORM_CONSTASCII_STRING( PROPERTY_APPLYDESIGNMODE, "ApplyFormDesignMode"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FORMATSSUPPLIER, "FormatsSupplier"); + XMLFORM_CONSTASCII_STRING( PROPERTY_LOCALE, "Locale"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FORMATSTRING, "FormatString"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DATEFORMAT, "DateFormat"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TIMEFORMAT, "TimeFormat"); + XMLFORM_CONSTASCII_STRING( PROPERTY_PERSISTENCE_MAXTEXTLENGTH, "PersistenceMaxTextLength"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SCROLLVALUE_MIN, "ScrollValueMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SCROLLVALUE_MAX, "ScrollValueMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SCROLLVALUE, "ScrollValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SCROLLVALUE_DEFAULT,"DefaultScrollValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_LINE_INCREMENT, "LineIncrement"); + XMLFORM_CONSTASCII_STRING( PROPERTY_BLOCK_INCREMENT, "BlockIncrement"); + XMLFORM_CONSTASCII_STRING( PROPERTY_REPEAT_DELAY, "RepeatDelay"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SPINVALUE, "SpinValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SPINVALUE_MIN, "SpinValueMin"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SPINVALUE_MAX, "SpinValueMax"); + XMLFORM_CONSTASCII_STRING( PROPERTY_DEFAULT_SPINVALUE, "DefaultSpinValue"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SPIN_INCREMENT, "SpinIncrement"); + XMLFORM_CONSTASCII_STRING( PROPERTY_ORIENTATION, "Orientation"); + XMLFORM_CONSTASCII_STRING( PROPERTY_TOGGLE, "Toggle"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FOCUS_ON_CLICK, "FocusOnClick"); + XMLFORM_CONSTASCII_STRING( PROPERTY_VISUAL_EFFECT, "VisualEffect"); + XMLFORM_CONSTASCII_STRING( PROPERTY_IMAGE_POSITION, "ImagePosition"); + XMLFORM_CONSTASCII_STRING( PROPERTY_IMAGE_ALIGN, "ImageAlign"); + XMLFORM_CONSTASCII_STRING( PROPERTY_SCALE_IMAGE, "ScaleImage"); + + XMLFORM_CONSTASCII_STRING( PROPERTY_BOUND_CELL, "BoundCell"); + XMLFORM_CONSTASCII_STRING( PROPERTY_LIST_CELL_RANGE, "CellRange"); + XMLFORM_CONSTASCII_STRING( PROPERTY_ADDRESS, "Address"); + XMLFORM_CONSTASCII_STRING( PROPERTY_FILE_REPRESENTATION,"PersistentRepresentation"); + XMLFORM_CONSTASCII_STRING( PROPERTY_RICH_TEXT, "RichText"); + + // services + XMLFORM_CONSTASCII_STRING( SERVICE_FORMSCOLLECTION, "com.sun.star.form.Forms" ); + XMLFORM_CONSTASCII_STRING( SERVICE_NUMBERFORMATSSUPPLIER, "com.sun.star.util.NumberFormatsSupplier" ); + XMLFORM_CONSTASCII_STRING( SERVICE_SPREADSHEET_DOCUMENT, "com.sun.star.sheet.SpreadsheetDocument"); + XMLFORM_CONSTASCII_STRING( SERVICE_CELLVALUEBINDING, "com.sun.star.table.CellValueBinding" ); + XMLFORM_CONSTASCII_STRING( SERVICE_LISTINDEXCELLBINDING, "com.sun.star.table.ListPositionCellBinding" ); + XMLFORM_CONSTASCII_STRING( SERVICE_CELLRANGELISTSOURCE, "com.sun.star.table.CellRangeListSource" ); + XMLFORM_CONSTASCII_STRING( SERVICE_ADDRESS_CONVERSION, "com.sun.star.table.CellAddressConversion"); + XMLFORM_CONSTASCII_STRING( SERVICE_RANGEADDRESS_CONVERSION, "com.sun.star.table.CellRangeAddressConversion"); + + // old service names (compatibility) + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_FORM, "stardiv.one.form.component.Form"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_EDIT, "stardiv.one.form.component.Edit"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_LISTBOX, "stardiv.one.form.component.ListBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_COMBOBOX, "stardiv.one.form.component.ComboBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_RADIOBUTTON, "stardiv.one.form.component.RadioButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_GROUPBOX, "stardiv.one.form.component.GroupBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_FIXEDTEXT, "stardiv.one.form.component.FixedText"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_COMMANDBUTTON, "stardiv.one.form.component.CommandButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_CHECKBOX, "stardiv.one.form.component.CheckBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_GRID, "stardiv.one.form.component.Grid"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_IMAGEBUTTON, "stardiv.one.form.component.ImageButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_FILECONTROL, "stardiv.one.form.component.FileControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_TIMEFIELD, "stardiv.one.form.component.TimeField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_DATEFIELD, "stardiv.one.form.component.DateField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_NUMERICFIELD, "stardiv.one.form.component.NumericField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_CURRENCYFIELD, "stardiv.one.form.component.CurrencyField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_PATTERNFIELD, "stardiv.one.form.component.PatternField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_HIDDENCONTROL, "stardiv.one.form.component.Hidden"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_IMAGECONTROL, "stardiv.one.form.component.ImageControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_PERSISTENT_COMPONENT_FORMATTEDFIELD, "stardiv.one.form.component.FormattedField"); + + // new service names, the old ones are translated into this new ones + XMLFORM_CONSTASCII_STRING( SERVICE_FORM, "com.sun.star.form.component.Form"); + XMLFORM_CONSTASCII_STRING( SERVICE_EDIT, "com.sun.star.form.component.TextField"); + XMLFORM_CONSTASCII_STRING( SERVICE_LISTBOX, "com.sun.star.form.component.ListBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_COMBOBOX, "com.sun.star.form.component.ComboBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_RADIOBUTTON, "com.sun.star.form.component.RadioButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_GROUPBOX, "com.sun.star.form.component.GroupBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_FIXEDTEXT, "com.sun.star.form.component.FixedText"); + XMLFORM_CONSTASCII_STRING( SERVICE_COMMANDBUTTON, "com.sun.star.form.component.CommandButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_CHECKBOX, "com.sun.star.form.component.CheckBox"); + XMLFORM_CONSTASCII_STRING( SERVICE_GRID, "com.sun.star.form.component.GridControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_IMAGEBUTTON, "com.sun.star.form.component.ImageButton"); + XMLFORM_CONSTASCII_STRING( SERVICE_FILECONTROL, "com.sun.star.form.component.FileControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_TIMEFIELD, "com.sun.star.form.component.TimeField"); + XMLFORM_CONSTASCII_STRING( SERVICE_DATEFIELD, "com.sun.star.form.component.DateField"); + XMLFORM_CONSTASCII_STRING( SERVICE_NUMERICFIELD, "com.sun.star.form.component.NumericField"); + XMLFORM_CONSTASCII_STRING( SERVICE_CURRENCYFIELD, "com.sun.star.form.component.CurrencyField"); + XMLFORM_CONSTASCII_STRING( SERVICE_PATTERNFIELD, "com.sun.star.form.component.PatternField"); + XMLFORM_CONSTASCII_STRING( SERVICE_HIDDENCONTROL, "com.sun.star.form.component.HiddenControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_IMAGECONTROL, "com.sun.star.form.component.DatabaseImageControl"); + XMLFORM_CONSTASCII_STRING( SERVICE_FORMATTEDFIELD, "com.sun.star.form.component.FormattedField" ); + + // various strings + XMLFORM_CONSTASCII_STRING( EVENT_NAME_SEPARATOR, "::" ); + XMLFORM_CONSTASCII_STRING( EVENT_TYPE, "EventType" ); + XMLFORM_CONSTASCII_STRING( EVENT_LIBRARY, "Library" ); + XMLFORM_CONSTASCII_STRING( EVENT_LOCALMACRONAME, "MacroName" ); + XMLFORM_CONSTASCII_STRING( EVENT_SCRIPTURL, "Script" ); + XMLFORM_CONSTASCII_STRING( EVENT_STAROFFICE, "StarOffice" ); + XMLFORM_CONSTASCII_STRING( EVENT_STARBASIC, "StarBasic" ); + XMLFORM_CONSTASCII_STRING( EVENT_APPLICATION, "application" ); + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_STRINGS_HXX_ diff --git a/xmloff/source/forms/valueproperties.cxx b/xmloff/source/forms/valueproperties.cxx new file mode 100644 index 000000000000..3515dcf96010 --- /dev/null +++ b/xmloff/source/forms/valueproperties.cxx @@ -0,0 +1,203 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" +#include "valueproperties.hxx" +#include "strings.hxx" +#include <com/sun/star/form/FormComponentType.hpp> + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + using namespace ::com::sun::star::form; + + //===================================================================== + //= OValuePropertiesMetaData + //===================================================================== + //--------------------------------------------------------------------- + void OValuePropertiesMetaData::getValuePropertyNames( + OControlElement::ElementType _eType, sal_Int16 _nFormComponentType, + sal_Char const * & _rpCurrentValuePropertyName, sal_Char const * & _rpValuePropertyName) + { + // reset the pointers in case we can't determine the property names + _rpCurrentValuePropertyName = _rpValuePropertyName = NULL; + switch (_nFormComponentType) + { + case FormComponentType::TEXTFIELD: + if (OControlElement::FORMATTED_TEXT == _eType) + { + _rpCurrentValuePropertyName = PROPERTY_EFFECTIVE_VALUE; + _rpValuePropertyName = PROPERTY_EFFECTIVE_DEFAULT; + } + else + { + if (OControlElement::PASSWORD != _eType) + // no CurrentValue" for passwords + _rpCurrentValuePropertyName = PROPERTY_TEXT; + _rpValuePropertyName = PROPERTY_DEFAULT_TEXT; + } + break; + + case FormComponentType::DATEFIELD: + _rpCurrentValuePropertyName = PROPERTY_DATE; + _rpValuePropertyName = PROPERTY_DEFAULT_DATE; + break; + + case FormComponentType::TIMEFIELD: + _rpCurrentValuePropertyName = PROPERTY_TIME; + _rpValuePropertyName = PROPERTY_DEFAULT_TIME; + break; + + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + _rpCurrentValuePropertyName = PROPERTY_VALUE; + _rpValuePropertyName = PROPERTY_DEFAULT_VALUE; + break; + + case FormComponentType::PATTERNFIELD: + case FormComponentType::FILECONTROL: + case FormComponentType::COMBOBOX: + _rpValuePropertyName = PROPERTY_DEFAULT_TEXT; + // NO BREAK!! + case FormComponentType::COMMANDBUTTON: + _rpCurrentValuePropertyName = PROPERTY_TEXT; + break; + + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + _rpValuePropertyName = PROPERTY_REFVALUE; + break; + + case FormComponentType::HIDDENCONTROL: + _rpValuePropertyName = PROPERTY_HIDDEN_VALUE; + break; + + case FormComponentType::SCROLLBAR: + _rpCurrentValuePropertyName = PROPERTY_SCROLLVALUE; + _rpValuePropertyName = PROPERTY_SCROLLVALUE_DEFAULT; + break; + + case FormComponentType::SPINBUTTON: + _rpCurrentValuePropertyName = PROPERTY_SPINVALUE; + _rpValuePropertyName = PROPERTY_DEFAULT_SPINVALUE; + break; + } + } + + + //--------------------------------------------------------------------- + void OValuePropertiesMetaData::getValueLimitPropertyNames(sal_Int16 _nFormComponentType, + sal_Char const * & _rpMinValuePropertyName, sal_Char const * & _rpMaxValuePropertyName) + { + _rpMinValuePropertyName = _rpMinValuePropertyName = NULL; + switch (_nFormComponentType) + { + case FormComponentType::DATEFIELD: + _rpMinValuePropertyName = PROPERTY_DATE_MIN; + _rpMaxValuePropertyName = PROPERTY_DATE_MAX; + break; + + case FormComponentType::TIMEFIELD: + _rpMinValuePropertyName = PROPERTY_TIME_MIN; + _rpMaxValuePropertyName = PROPERTY_TIME_MAX; + break; + + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + _rpMinValuePropertyName = PROPERTY_VALUE_MIN; + _rpMaxValuePropertyName = PROPERTY_VALUE_MAX; + break; + + case FormComponentType::TEXTFIELD: + _rpMinValuePropertyName = PROPERTY_EFFECTIVE_MIN; + _rpMaxValuePropertyName = PROPERTY_EFFECTIVE_MAX; + break; + + case FormComponentType::SCROLLBAR: + _rpMinValuePropertyName = PROPERTY_SCROLLVALUE_MIN; + _rpMaxValuePropertyName = PROPERTY_SCROLLVALUE_MAX; + break; + + case FormComponentType::SPINBUTTON: + _rpMinValuePropertyName = PROPERTY_SPINVALUE_MIN; + _rpMaxValuePropertyName = PROPERTY_SPINVALUE_MAX; + break; + } + } + + //--------------------------------------------------------------------- + void OValuePropertiesMetaData::getRuntimeValuePropertyNames( + OControlElement::ElementType _eType, sal_Int16 _nFormComponentType, + sal_Char const * & _rpValuePropertyName, sal_Char const * & _rpDefaultValuePropertyName ) + { + // reset the pointers in case we can't determine the property names + _rpValuePropertyName = _rpDefaultValuePropertyName = NULL; + switch (_nFormComponentType) + { + case FormComponentType::TEXTFIELD: + if (OControlElement::FORMATTED_TEXT == _eType) + { + _rpValuePropertyName = PROPERTY_EFFECTIVE_VALUE; + _rpDefaultValuePropertyName = PROPERTY_EFFECTIVE_DEFAULT; + } + else + { + _rpValuePropertyName = PROPERTY_TEXT; + _rpDefaultValuePropertyName = PROPERTY_DEFAULT_TEXT; + } + break; + + case FormComponentType::DATEFIELD: + case FormComponentType::TIMEFIELD: + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + case FormComponentType::PATTERNFIELD: + case FormComponentType::FILECONTROL: + case FormComponentType::COMBOBOX: + case FormComponentType::SCROLLBAR: + case FormComponentType::SPINBUTTON: + // For these types, the runtime properties are the same as the ones which in the XML + // stream are named "value properties" + getValuePropertyNames( _eType, _nFormComponentType, _rpValuePropertyName, _rpDefaultValuePropertyName ); + break; + + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + _rpValuePropertyName = PROPERTY_STATE; + _rpDefaultValuePropertyName = PROPERTY_DEFAULT_STATE; + break; + } + } + +//......................................................................... +} // namespace xmloff +//......................................................................... + + diff --git a/xmloff/source/forms/valueproperties.hxx b/xmloff/source/forms/valueproperties.hxx new file mode 100644 index 000000000000..95f2b13d1880 --- /dev/null +++ b/xmloff/source/forms/valueproperties.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLOFF_FORMS_VALUEPROPERTIES_HXX_ +#define _XMLOFF_FORMS_VALUEPROPERTIES_HXX_ + +#include "controlelement.hxx" + +//......................................................................... +namespace xmloff +{ +//......................................................................... + + //===================================================================== + //= OValuePropertiesMetaData + //===================================================================== + class OValuePropertiesMetaData + { + protected: + OValuePropertiesMetaData() { } + + public: + /** calculate the property names for the <em>current-value</em> and the <em>value</em> attribute. + + <p>If controls of the given FormComponentType do not have any of the properties requested, + the respective out parameter will be set to NULL.</p> + */ + static void getValuePropertyNames( + OControlElement::ElementType _eType, + sal_Int16 _nFormComponentType, + sal_Char const * & _rpCurrentValuePropertyName, + sal_Char const * & _rpValuePropertyName); + + /** calculate the property names for the <em>min-value</em> and the <em>max-value</em> attribute. + + <p>If controls of the given FormComponentType do not have any of the properties requested, + the respective out parameter will be set to NULL.</p> + */ + static void getValueLimitPropertyNames( + sal_Int16 _nFormComponentType, + sal_Char const * & _rpMinValuePropertyName, + sal_Char const * & _rpMaxValuePropertyName); + + /** calculate the names of the properties which, at runtime, are used for <em>value</em> and + <em>default value</em>. + */ + static void getRuntimeValuePropertyNames( + OControlElement::ElementType _eType, + sal_Int16 _nFormComponentType, + sal_Char const * & _rpValuePropertyName, + sal_Char const * & _rpDefaultValuePropertyName); + }; + +//......................................................................... +} // namespace xmloff +//......................................................................... + +#endif // _XMLOFF_FORMS_VALUEPROPERTIES_HXX_ + + |