diff options
Diffstat (limited to 'xmloff/source/forms/elementexport.cxx')
-rw-r--r-- | xmloff/source/forms/elementexport.cxx | 2260 |
1 files changed, 2260 insertions, 0 deletions
diff --git a/xmloff/source/forms/elementexport.cxx b/xmloff/source/forms/elementexport.cxx new file mode 100644 index 000000000000..149965631b27 --- /dev/null +++ b/xmloff/source/forms/elementexport.cxx @@ -0,0 +1,2260 @@ +/************************************************************************* + * + * 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" +#include "property_meta_data.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!"); + m_rContext.getGlobalContext().AddAttributeIdLegacy( + XML_NAMESPACE_FORM, m_sControlId); + #if OSL_DEBUG_LEVEL > 0 + // reset the bit for later checking + m_nIncludeCommon = m_nIncludeCommon & ~CCA_CONTROL_ID; + #endif + } + + // "new-style" properties ... + exportGenericHandlerAttributes(); + + // 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::exportGenericHandlerAttributes() + { + const Sequence< Property > aProperties = m_xPropertyInfo->getProperties(); + for ( const Property* prop = aProperties.getConstArray(); + prop != aProperties.getConstArray() + aProperties.getLength(); + ++prop + ) + { + try + { + // see if this property can already be handled with an IPropertyHandler (which, on the long + // term, should be the case for most, if not all, properties) + const PropertyDescription* propDescription = metadata::getPropertyDescription( prop->Name ); + if ( propDescription == NULL ) + continue; + + // let the factory provide the concrete handler. Note that caching, if desired, is the task + // of the factory + PPropertyHandler handler = (*propDescription->factory)( propDescription->propertyId ); + ENSURE_OR_CONTINUE( handler.get() != NULL, + "OControlExport::exportGenericHandlerAttributes: invalid property handler provided by the factory!" ); + + ::rtl::OUString attributeValue; + if ( propDescription->propertyGroup == NO_GROUP ) + { + // that's a property which has a direct mapping to an attribute + if ( !shouldExportProperty( prop->Name ) ) + // TODO: in the future, we surely need a more sophisticated approach to this, involving the property + // handler, or the property description + { + exportedProperty( prop->Name ); + continue; + } + + const Any propValue = m_xProps->getPropertyValue( prop->Name ); + attributeValue = handler->getAttributeValue( propValue ); + } + else + { + // that's a property which is part of a group of properties, whose values, in their entity, comprise + // a single attribute value + + // retrieve the descriptions of all other properties which add to the attribute value + PropertyDescriptionList descriptions; + metadata::getPropertyGroup( propDescription->propertyGroup, descriptions ); + + // retrieve the values for all those properties + PropertyValues aValues; + for ( PropertyDescriptionList::iterator desc = descriptions.begin(); + desc != descriptions.end(); + ++desc + ) + { + // TODO: XMultiPropertySet? + const Any propValue = m_xProps->getPropertyValue( (*desc)->propertyName ); + aValues[ (*desc)->propertyId ] = propValue; + } + + // let the handler translate into an XML attribute value + attributeValue = handler->getAttributeValue( aValues ); + } + + AddAttribute( + propDescription->attribute.namespacePrefix, + token::GetXMLToken( propDescription->attribute.attributeToken ), + attributeValue + ); + + exportedProperty( prop->Name ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + //--------------------------------------------------------------------- + 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(false); + #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; + bool knownType = false; + switch (m_nClassId) + { + case FormComponentType::DATEFIELD: + m_eType = DATE; + knownType = true; + // NO BREAK + case FormComponentType::TIMEFIELD: + if ( !knownType ) + { + m_eType = TIME; + knownType = true; + } + m_nIncludeSpecial |= SCA_VALIDATION; + // NO BREAK + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + case FormComponentType::PATTERNFIELD: + if ( !knownType ) + { + m_eType = FORMATTED_TEXT; + knownType = true; + } + // NO BREAK + case FormComponentType::TEXTFIELD: + { // it's some kind of edit. To know which type we need further investigation + + if ( !knownType ) + { + // 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; + } + } + knownType = true; + } + + // attributes which are common to all the types: + // common attributes + m_nIncludeCommon = + CCA_NAME | CCA_SERVICE_NAME | CCA_DISABLED | + CCA_PRINTABLE | CCA_TAB_INDEX | CCA_TAB_STOP | CCA_TITLE; + + if ( ( m_nClassId != FormComponentType::DATEFIELD ) + && ( m_nClassId != FormComponentType::TIMEFIELD ) + ) + // date and time field values are handled differently nowadays + m_nIncludeCommon |= CCA_VALUE; + + // 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 ) // except the PatternField + 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 ) + && ( DATE != m_eType ) + && ( TIME != 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]); + + // #i112082# xlink:type is added as part of exportTargetLocationAttribute + + // 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(true); // #i110911# add type attribute (for form, but not for control) + + // master fields + exportStringSequenceAttribute( + OAttributeMetaData::getFormAttributeNamespace(faMasterFields), + OAttributeMetaData::getFormAttributeName(faMasterFields), + PROPERTY_MASTERFIELDS); + // detail fields + exportStringSequenceAttribute( + OAttributeMetaData::getFormAttributeNamespace(faDetailFiels), + OAttributeMetaData::getFormAttributeName(faDetailFiels), + PROPERTY_DETAILFIELDS); + } +//......................................................................... +} // namespace xmloff +//......................................................................... |