Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / xmloff / source / forms / elementexport.cxx
blobaf4e7585feff064d535a5dee15da5bbf7b86fc4f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "elementexport.hxx"
22 #include "strings.hxx"
23 #include <utility>
24 #include <xmloff/xmlnamespace.hxx>
25 #include "eventexport.hxx"
26 #include "formenums.hxx"
27 #include "formcellbinding.hxx"
28 #include <xmloff/xformsexport.hxx>
29 #include "property_meta_data.hxx"
31 #include <com/sun/star/text/XText.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/io/XPersistObject.hpp>
34 #include <com/sun/star/util/Duration.hpp>
35 #include <com/sun/star/form/FormComponentType.hpp>
36 #include <com/sun/star/form/FormSubmitEncoding.hpp>
37 #include <com/sun/star/form/FormSubmitMethod.hpp>
38 #include <com/sun/star/sdb/CommandType.hpp>
39 #include <com/sun/star/form/NavigationBarMode.hpp>
40 #include <com/sun/star/form/TabulatorCycle.hpp>
41 #include <com/sun/star/form/FormButtonType.hpp>
42 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
43 #include <com/sun/star/awt/VisualEffect.hpp>
44 #include <com/sun/star/form/ListSourceType.hpp>
45 #include <com/sun/star/awt/ImagePosition.hpp>
47 #include <sax/tools/converter.hxx>
48 #include <tools/gen.hxx>
49 #include <xmloff/txtprmap.hxx>
50 #include <com/sun/star/form/binding/XBindableValue.hpp>
51 #include <com/sun/star/form/binding/XListEntrySink.hpp>
52 #include <tools/urlobj.hxx>
53 #include <xmloff/xmlexp.hxx>
54 #include <xmloff/namespacemap.hxx>
55 #include <xmloff/XMLEventExport.hxx>
56 #include <xmloff/xmluconv.hxx>
57 #include <xmloff/xmltoken.hxx>
58 #include <xmloff/maptype.hxx>
59 #include <tools/time.hxx>
60 #include <comphelper/diagnose_ex.hxx>
61 #include <comphelper/extract.hxx>
62 #include <sal/macros.h>
63 #include <sal/log.hxx>
65 #include <algorithm>
66 #include <string_view>
68 namespace xmloff
71 #if OSL_DEBUG_LEVEL > 0
72 #define RESET_BIT( bitfield, bit ) \
73 bitfield = bitfield & ~bit
74 #else
75 #define RESET_BIT( bitfield, bit )
76 #endif
78 using namespace ::xmloff::token;
79 using namespace ::com::sun::star;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star::sdb;
82 using namespace ::com::sun::star::awt;
83 using namespace ::com::sun::star::form;
84 using namespace ::com::sun::star::lang;
85 using namespace ::com::sun::star::beans;
86 using namespace ::com::sun::star::container;
87 using namespace ::com::sun::star::script;
88 using namespace ::com::sun::star::io;
89 using namespace ::com::sun::star::table;
90 using namespace ::com::sun::star::text;
91 using namespace ::com::sun::star::form::binding;
93 //= OElementExport
94 OElementExport::OElementExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxProps,
95 const Sequence< ScriptEventDescriptor >& _rEvents)
96 :OPropertyExport(_rContext, _rxProps)
97 ,m_aEvents(_rEvents)
101 OElementExport::~OElementExport()
105 void OElementExport::doExport()
107 // collect some general information about the element
108 examine();
110 // first add the attributes necessary for the element
111 m_rContext.getGlobalContext().ClearAttrList();
113 // add the attributes
114 exportAttributes();
116 // start the XML element
117 implStartElement(getXMLElementName());
119 // the sub elements (mostly control type dependent)
120 exportSubTags();
122 implEndElement();
125 void OElementExport::examine()
127 // nothing to do here
130 void OElementExport::exportAttributes()
132 // nothing to do here
135 void OElementExport::exportSubTags()
137 // the properties which where not exported 'til now
138 exportRemainingProperties();
140 // the script:events sub tags
141 exportEvents();
144 void OElementExport::implStartElement(const char* _pName)
146 m_pXMLElement = std::make_unique<SvXMLElementExport>(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, _pName, true, true);
149 void OElementExport::implEndElement()
151 m_pXMLElement.reset();
154 void OElementExport::exportServiceNameAttribute()
156 Reference< XPersistObject > xPersistence(m_xProps, UNO_QUERY);
157 if (!xPersistence.is())
159 OSL_FAIL("OElementExport::exportServiceNameAttribute: no XPersistObject!");
160 return;
163 OUString sServiceName = xPersistence->getServiceName();
164 // we don't want to write the old service name directly: it's a name used for compatibility reasons, but
165 // as we start some kind of new file format here (with this xml export), we don't care about
166 // compatibility ...
167 // So we translate the old persistence service name into new ones, if possible
169 OUString sToWriteServiceName = sServiceName;
170 #define CHECK_N_TRANSLATE( name ) \
171 else if (sServiceName == SERVICE_PERSISTENT_COMPONENT_##name) \
172 sToWriteServiceName = SERVICE_##name
174 if (sServiceName == SERVICE_PERSISTENT_COMPONENT_EDIT)
176 // special handling for the edit field: we have two controls using this as persistence service name
177 sToWriteServiceName = SERVICE_EDIT;
178 Reference< XServiceInfo > xSI(m_xProps, UNO_QUERY);
179 if (xSI.is() && xSI->supportsService(SERVICE_FORMATTEDFIELD))
180 sToWriteServiceName = SERVICE_FORMATTEDFIELD;
182 CHECK_N_TRANSLATE( FORM );
183 CHECK_N_TRANSLATE( LISTBOX );
184 CHECK_N_TRANSLATE( COMBOBOX );
185 CHECK_N_TRANSLATE( RADIOBUTTON );
186 CHECK_N_TRANSLATE( GROUPBOX );
187 CHECK_N_TRANSLATE( FIXEDTEXT );
188 CHECK_N_TRANSLATE( COMMANDBUTTON );
189 CHECK_N_TRANSLATE( CHECKBOX );
190 CHECK_N_TRANSLATE( GRID );
191 CHECK_N_TRANSLATE( IMAGEBUTTON );
192 CHECK_N_TRANSLATE( FILECONTROL );
193 CHECK_N_TRANSLATE( TIMEFIELD );
194 CHECK_N_TRANSLATE( DATEFIELD );
195 CHECK_N_TRANSLATE( NUMERICFIELD );
196 CHECK_N_TRANSLATE( CURRENCYFIELD );
197 CHECK_N_TRANSLATE( PATTERNFIELD );
198 CHECK_N_TRANSLATE( HIDDENCONTROL );
199 CHECK_N_TRANSLATE( IMAGECONTROL );
200 CHECK_N_TRANSLATE( FORMATTEDFIELD );
201 #if OSL_DEBUG_LEVEL > 0
202 Reference< XServiceInfo > xSI(m_xProps, UNO_QUERY);
203 OSL_ENSURE(xSI.is() && xSI->supportsService(sToWriteServiceName),
204 "OElementExport::exportServiceNameAttribute: wrong service name translation!");
206 #endif
207 sToWriteServiceName =
208 m_rContext.getGlobalContext().GetNamespaceMap().GetQNameByKey(
209 XML_NAMESPACE_OOO, sToWriteServiceName );
211 // now write this
212 AddAttribute(
213 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::ServiceName),
214 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::ServiceName),
215 sToWriteServiceName);
218 void OElementExport::exportEvents()
220 if (!m_aEvents.hasElements())
221 // nothing to do
222 return;
224 Reference< XNameReplace > xWrapper = new OEventDescriptorMapper(m_aEvents);
225 m_rContext.getGlobalContext().GetEventExport().Export(xWrapper);
228 //= OControlExport
229 OControlExport::OControlExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxControl,
230 OUString _sControlId, OUString _sReferringControls,
231 const Sequence< ScriptEventDescriptor >& _rEvents)
232 :OElementExport(_rContext, _rxControl, _rEvents)
233 ,m_sControlId(std::move(_sControlId))
234 ,m_sReferringControls(std::move(_sReferringControls))
235 ,m_nClassId(FormComponentType::CONTROL)
236 ,m_eType( UNKNOWN )
237 ,m_nIncludeCommon(CCAFlags::NONE)
238 ,m_nIncludeDatabase(DAFlags::NONE)
239 ,m_nIncludeSpecial(SCAFlags::NONE)
240 ,m_nIncludeEvents(EAFlags::NONE)
241 ,m_nIncludeBindings(BAFlags::NONE)
243 OSL_ENSURE(m_xProps.is(), "OControlExport::OControlExport: invalid arguments!");
246 void OControlExport::exportOuterAttributes()
248 // the control id
249 if (CCAFlags::Name & m_nIncludeCommon)
251 exportStringPropertyAttribute(
252 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Name),
253 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Name),
254 PROPERTY_NAME
256 #if OSL_DEBUG_LEVEL > 0
257 // reset the bit for later checking
258 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::Name;
259 #endif
262 // the service name
263 if (m_nIncludeCommon & CCAFlags::ServiceName)
265 exportServiceNameAttribute();
266 #if OSL_DEBUG_LEVEL > 0
267 // reset the bit for later checking
268 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::ServiceName;
269 #endif
273 void OControlExport::exportInnerAttributes()
275 // the control id
276 if (CCAFlags::ControlId & m_nIncludeCommon)
278 OSL_ENSURE(!m_sControlId.isEmpty(), "OControlExport::exportInnerAttributes: have no control id for the control!");
279 m_rContext.getGlobalContext().AddAttributeIdLegacy(
280 XML_NAMESPACE_FORM, m_sControlId);
281 #if OSL_DEBUG_LEVEL > 0
282 // reset the bit for later checking
283 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::ControlId;
284 #endif
287 // "new-style" properties ...
288 exportGenericHandlerAttributes();
290 // common control attributes
291 exportCommonControlAttributes();
293 // common database attributes
294 exportDatabaseAttributes();
296 // attributes related to external bindings
297 exportBindingAttributes();
299 // attributes special to the respective control type
300 exportSpecialAttributes();
302 // add the style references to the attributes
303 flagStyleProperties();
306 void OControlExport::exportAttributes()
308 exportOuterAttributes();
311 void OControlExport::exportSubTags()
313 // for the upcoming exportRemainingProperties:
314 // if a control has the LabelControl property, this is not stored with the control itself, but instead with
315 // the control which is referenced by this property. As the base class' exportRemainingProperties doesn't
316 // know anything about this, we need to prevent that it tries to export this property
317 exportedProperty(PROPERTY_CONTROLLABEL);
319 // if it's a control supporting XText, then we need to declare all text-related properties
320 // as "already exported". This prevents them from being exported as generic "form:property"-tags.
321 // *If* we would export them this way, they would be completely superfluous, and sometimes even
322 // disastrous, since they may, at import time, override paragraph properties which already have
323 // been set before
324 Reference< XText > xControlText( m_xProps, UNO_QUERY );
325 if ( xControlText.is() )
327 const XMLPropertyMapEntry* pCharAttributeProperties = XMLTextPropertySetMapper::getPropertyMapForType( TextPropMap::TEXT );
328 while ( !pCharAttributeProperties->IsEnd() )
330 exportedProperty( pCharAttributeProperties->getApiName() );
331 ++pCharAttributeProperties;
334 const XMLPropertyMapEntry* pParaAttributeProperties = XMLTextPropertySetMapper::getPropertyMapForType( TextPropMap::SHAPE_PARA );
335 while ( !pParaAttributeProperties->IsEnd() )
337 exportedProperty( pParaAttributeProperties->getApiName() );
338 ++pParaAttributeProperties;
341 // the RichText property is not exported. The presence of the text:p element
342 // will be used - upon reading - as indicator for the value of the RichText property
343 exportedProperty( PROPERTY_RICH_TEXT );
345 // strange thing: paragraphs support both a CharStrikeout and a CharCrossedOut property
346 // The former is a short/enum value, the latter a boolean. The former has a real meaning
347 // (the strikeout type), the latter hasn't. But, when the CharCrossedOut is exported and
348 // later on imported, it overwrites anything which has previously been imported for
349 // CharStrikeout.
350 // #i27729#
351 exportedProperty( "CharCrossedOut" );
354 if ( m_eType == LISTBOX )
356 // will be exported in exportListSourceAsElements:
357 if ( controlHasUserSuppliedListEntries() )
358 exportedProperty( PROPERTY_DEFAULT_SELECT_SEQ );
360 // will not be exported in a generic way. Either exportListSourceAsElements cares
361 // for them, or we don't need them
362 exportedProperty( PROPERTY_STRING_ITEM_LIST );
363 exportedProperty( PROPERTY_VALUE_SEQ );
364 exportedProperty( PROPERTY_SELECT_SEQ );
365 exportedProperty( PROPERTY_LISTSOURCE );
367 if ( m_eType == COMBOBOX )
368 exportedProperty( PROPERTY_STRING_ITEM_LIST );
370 // let the base class export the remaining properties and the events
371 OElementExport::exportSubTags();
373 // special sub tags for some controls
374 switch (m_eType)
376 case LISTBOX:
377 // don't export the list entries if the are not provided by the user, but obtained implicitly
378 // from other sources
379 // #i26944#
380 if ( controlHasUserSuppliedListEntries() )
381 exportListSourceAsElements();
382 break;
383 case GRID:
384 { // a grid control requires us to store all columns as sub elements
385 Reference< XIndexAccess > xColumnContainer(m_xProps, UNO_QUERY);
386 OSL_ENSURE(xColumnContainer.is(), "OControlExport::exportSubTags: a grid control which is no IndexAccess?!!");
387 if (xColumnContainer.is())
388 m_rContext.exportCollectionElements(xColumnContainer);
390 break;
391 case COMBOBOX:
392 { // a combox box description has sub elements: the items
393 DBG_CHECK_PROPERTY( PROPERTY_STRING_ITEM_LIST, Sequence< OUString > );
395 // don't export the list entries if the are not provided by the user, but obtained implicitly
396 // from other sources
397 // #i26944#
398 if ( controlHasUserSuppliedListEntries() )
400 // get the item list
401 Sequence< OUString > aListItems;
402 m_xProps->getPropertyValue(PROPERTY_STRING_ITEM_LIST) >>= aListItems;
403 // loop through it and write the sub elements
404 for (const auto& rListItem : std::as_const(aListItems))
406 m_rContext.getGlobalContext().ClearAttrList();
407 AddAttribute(
408 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Label),
409 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Label),
410 rListItem);
411 SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "item", true, true);
415 break;
417 case TEXT_AREA:
419 // if we act as rich text control, we need to export some text:p elements
420 if ( xControlText.is() )
422 bool bActingAsRichText = false;
423 if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_RICH_TEXT ) )
425 OSL_VERIFY(m_xProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActingAsRichText );
428 if ( bActingAsRichText )
429 m_rContext.getGlobalContext().GetTextParagraphExport()->exportText( xControlText );
432 break;
433 default:
434 // nothing do to
435 break;
439 void OControlExport::exportGenericHandlerAttributes()
441 const Sequence< Property > aProperties = m_xPropertyInfo->getProperties();
442 for ( auto const & prop : aProperties )
446 // see if this property can already be handled with an IPropertyHandler (which, on the long
447 // term, should be the case for most, if not all, properties)
448 const PropertyDescription* propDescription = metadata::getPropertyDescription( prop.Name );
449 if ( propDescription == nullptr )
450 continue;
452 // let the factory provide the concrete handler. Note that caching, if desired, is the task
453 // of the factory
454 PPropertyHandler handler = (*propDescription->factory)( propDescription->propertyId );
455 if ( !handler )
457 SAL_WARN( "xmloff.forms", "OControlExport::exportGenericHandlerAttributes: invalid property handler provided by the factory!" );
458 continue;
461 // that's a property which has a direct mapping to an attribute
462 if ( !shouldExportProperty( prop.Name ) )
463 // TODO: in the future, we surely need a more sophisticated approach to this, involving the property
464 // handler, or the property description
466 exportedProperty( prop.Name );
467 continue;
470 const Any propValue = m_xProps->getPropertyValue( prop.Name );
471 OUString attributeValue = handler->getAttributeValue( propValue );
473 AddAttribute(
474 propDescription->attribute.namespacePrefix,
475 token::GetXMLToken( propDescription->attribute.attributeToken ),
476 attributeValue
479 exportedProperty( prop.Name );
481 catch( const Exception& )
483 DBG_UNHANDLED_EXCEPTION("xmloff.forms");
488 void OControlExport::exportCommonControlAttributes()
490 size_t i=0;
492 // I decided to handle all the properties here with some static arrays describing the property-attribute
493 // relations. This leads to somewhat ugly code :), but the only alternative I can think of right now
494 // would require maps and O(log n) searches, which seems somewhat expensive as this code is used
495 // very frequently.
497 // the extra indents for the respective blocks are to ensure that there is no copy'n'paste error, using
498 // map identifiers from the wrong block
500 // some string properties
502 // the attribute ids of all properties which are expected to be of type string
503 static const CCAFlags nStringPropertyAttributeIds[] =
505 CCAFlags::Label, CCAFlags::Title
507 // the names of all properties which are expected to be of type string
508 static const rtl::OUStringConstExpr aStringPropertyNames[] =
510 PROPERTY_LABEL, PROPERTY_TITLE
512 OSL_ENSURE( std::size(aStringPropertyNames) ==
513 std::size(nStringPropertyAttributeIds),
514 "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (1)!");
516 for (i=0; i<std::size(nStringPropertyAttributeIds); ++i)
517 if (nStringPropertyAttributeIds[i] & m_nIncludeCommon)
519 exportStringPropertyAttribute(
520 OAttributeMetaData::getCommonControlAttributeNamespace(nStringPropertyAttributeIds[i]),
521 OAttributeMetaData::getCommonControlAttributeName(nStringPropertyAttributeIds[i]),
522 aStringPropertyNames[i]
524 #if OSL_DEBUG_LEVEL > 0
525 // reset the bit for later checking
526 m_nIncludeCommon = m_nIncludeCommon & ~nStringPropertyAttributeIds[i];
527 #endif
531 // some boolean properties
533 static const CCAFlags nBooleanPropertyAttributeIds[] =
534 { // attribute flags
535 CCAFlags::CurrentSelected, CCAFlags::Disabled, CCAFlags::Dropdown, CCAFlags::Printable, CCAFlags::ReadOnly, CCAFlags::Selected, CCAFlags::TabStop, CCAFlags::EnableVisible
537 static const rtl::OUStringConstExpr pBooleanPropertyNames[] =
538 { // property names
539 PROPERTY_STATE, PROPERTY_ENABLED,
540 PROPERTY_DROPDOWN, PROPERTY_PRINTABLE,
541 PROPERTY_READONLY, PROPERTY_DEFAULT_STATE,
542 PROPERTY_TABSTOP, PROPERTY_ENABLEVISIBLE
544 static const BoolAttrFlags nBooleanPropertyAttrFlags[] =
545 { // attribute defaults
546 BoolAttrFlags::DefaultFalse, BoolAttrFlags::DefaultFalse | BoolAttrFlags::InverseSemantics, BoolAttrFlags::DefaultFalse, BoolAttrFlags::DefaultTrue, BoolAttrFlags::DefaultFalse, BoolAttrFlags::DefaultFalse, BoolAttrFlags::DefaultVoid, BoolAttrFlags::DefaultFalse
548 #if OSL_DEBUG_LEVEL > 0
549 static const sal_Int32 nIdCount = std::size(nBooleanPropertyAttributeIds);
550 static const sal_Int32 nNameCount = std::size(pBooleanPropertyNames);
551 static const sal_Int32 nFlagsCount = std::size(nBooleanPropertyAttrFlags);
552 OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nFlagsCount),
553 "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (2)!");
554 #endif
555 for (i=0; i<std::size(nBooleanPropertyAttributeIds); ++i)
556 if (nBooleanPropertyAttributeIds[i] & m_nIncludeCommon)
558 exportBooleanPropertyAttribute(
559 OAttributeMetaData::getCommonControlAttributeNamespace(nBooleanPropertyAttributeIds[i]),
560 OAttributeMetaData::getCommonControlAttributeName(nBooleanPropertyAttributeIds[i]),
561 pBooleanPropertyNames[i],
562 nBooleanPropertyAttrFlags[i]);
563 #if OSL_DEBUG_LEVEL > 0
564 // reset the bit for later checking
565 m_nIncludeCommon = m_nIncludeCommon & ~nBooleanPropertyAttributeIds[i];
566 #endif
570 // some integer properties
572 // now the common handling
573 static const CCAFlags nIntegerPropertyAttributeIds[] =
574 { // attribute flags
575 CCAFlags::Size, CCAFlags::TabIndex
577 static const rtl::OUStringConstExpr pIntegerPropertyNames[] =
578 { // property names
579 PROPERTY_LINECOUNT, PROPERTY_TABINDEX
581 static const sal_Int16 nIntegerPropertyAttrDefaults[] =
582 { // attribute defaults
583 5, 0
586 if ( m_nIncludeCommon & CCAFlags::MaxLength )
587 exportedProperty(PROPERTY_MAXTEXTLENGTH);
589 #if OSL_DEBUG_LEVEL > 0
590 static const sal_Int32 nIdCount = std::size(nIntegerPropertyAttributeIds);
591 static const sal_Int32 nNameCount = std::size(pIntegerPropertyNames);
592 static const sal_Int32 nDefaultCount = std::size(nIntegerPropertyAttrDefaults);
593 OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nDefaultCount),
594 "OControlExport::exportCommonControlAttributes: somebody tampered with the maps (3)!");
595 #endif
596 for (i=0; i<std::size(nIntegerPropertyAttributeIds); ++i)
597 if (nIntegerPropertyAttributeIds[i] & m_nIncludeCommon)
599 exportInt16PropertyAttribute(
600 OAttributeMetaData::getCommonControlAttributeNamespace(nIntegerPropertyAttributeIds[i]),
601 OAttributeMetaData::getCommonControlAttributeName(nIntegerPropertyAttributeIds[i]),
602 pIntegerPropertyNames[i],
603 nIntegerPropertyAttrDefaults[i]);
604 #if OSL_DEBUG_LEVEL > 0
605 // reset the bit for later checking
606 m_nIncludeCommon = m_nIncludeCommon & ~nIntegerPropertyAttributeIds[i];
607 #endif
612 // some enum properties
614 if (m_nIncludeCommon & CCAFlags::ButtonType)
616 exportEnumPropertyAttribute(
617 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::ButtonType),
618 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::ButtonType),
619 PROPERTY_BUTTONTYPE,
620 aFormButtonTypeMap,
621 FormButtonType_PUSH);
622 #if OSL_DEBUG_LEVEL > 0
623 // reset the bit for later checking
624 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::ButtonType;
625 #endif
627 if ( m_nIncludeCommon & CCAFlags::Orientation )
629 exportEnumPropertyAttribute(
630 OAttributeMetaData::getCommonControlAttributeNamespace( CCAFlags::Orientation ),
631 OAttributeMetaData::getCommonControlAttributeName( CCAFlags::Orientation ),
632 PROPERTY_ORIENTATION,
633 aOrientationMap,
634 ScrollBarOrientation::HORIZONTAL
636 #if OSL_DEBUG_LEVEL > 0
637 // reset the bit for later checking
638 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::Orientation;
639 #endif
642 if ( m_nIncludeCommon & CCAFlags::VisualEffect )
644 exportEnumPropertyAttribute(
645 OAttributeMetaData::getCommonControlAttributeNamespace( CCAFlags::VisualEffect ),
646 OAttributeMetaData::getCommonControlAttributeName( CCAFlags::VisualEffect ),
647 PROPERTY_VISUAL_EFFECT,
648 aVisualEffectMap,
649 VisualEffect::LOOK3D
651 #if OSL_DEBUG_LEVEL > 0
652 // reset the bit for later checking
653 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::VisualEffect;
654 #endif
658 // some properties which require a special handling
660 // the target frame
661 if (m_nIncludeCommon & CCAFlags::TargetFrame)
663 exportTargetFrameAttribute();
664 #if OSL_DEBUG_LEVEL > 0
665 // reset the bit for later checking
666 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::TargetFrame;
667 #endif
670 // max text length
671 if ( m_nIncludeCommon & CCAFlags::MaxLength )
673 // normally, the respective property would be "MaxTextLen"
674 // However, if the model has a property "PersistenceMaxTextLength", then we prefer this
676 // determine the name of the property to export
677 OUString sTextLenPropertyName( PROPERTY_MAXTEXTLENGTH );
678 if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_PERSISTENCE_MAXTEXTLENGTH ) )
679 sTextLenPropertyName = PROPERTY_PERSISTENCE_MAXTEXTLENGTH;
681 // export it
682 exportInt16PropertyAttribute(
683 OAttributeMetaData::getCommonControlAttributeNamespace( CCAFlags::MaxLength ),
684 OAttributeMetaData::getCommonControlAttributeName( CCAFlags::MaxLength ),
685 sTextLenPropertyName,
689 // in either way, both properties count as "exported"
690 exportedProperty( PROPERTY_MAXTEXTLENGTH );
691 exportedProperty( PROPERTY_PERSISTENCE_MAXTEXTLENGTH );
693 #if OSL_DEBUG_LEVEL > 0
694 // reset the bit for later checking
695 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::MaxLength;
696 #endif
699 if (m_nIncludeCommon & CCAFlags::TargetLocation)
701 exportTargetLocationAttribute(false);
702 #if OSL_DEBUG_LEVEL > 0
703 // reset the bit for later checking
704 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::TargetLocation;
705 #endif
708 // OJ #99721#
709 if (m_nIncludeCommon & CCAFlags::ImageData)
711 exportImageDataAttribute();
712 #if OSL_DEBUG_LEVEL > 0
713 // reset the bit for later checking
714 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::ImageData;
715 #endif
718 // the for attribute
719 // the target frame
720 if (m_nIncludeCommon & CCAFlags::For)
722 if (!m_sReferringControls.isEmpty())
723 { // there is at least one control referring to the one we're handling currently
724 AddAttribute(
725 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::For),
726 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::For),
727 m_sReferringControls);
729 #if OSL_DEBUG_LEVEL > 0
730 // reset the bit for later checking
731 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags::For;
732 #endif
735 if ((CCAFlags::CurrentValue | CCAFlags::Value) & m_nIncludeCommon)
737 OUString pCurrentValuePropertyName;
738 OUString pValuePropertyName;
740 // get the property names
741 getValuePropertyNames(m_eType, m_nClassId, pCurrentValuePropertyName, pValuePropertyName);
743 // add the attributes if necessary and possible
744 if (!pCurrentValuePropertyName.isEmpty() && (CCAFlags::CurrentValue & m_nIncludeCommon))
746 static const OUString pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentValue);
747 // don't export the current-value if this value originates from a data binding
748 // #i26944#
749 if ( controlHasActiveDataBinding() )
750 exportedProperty( pCurrentValuePropertyName );
751 else
753 static const sal_uInt16 nCurrentValueAttributeNamespaceKey = OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::CurrentValue);
754 exportGenericPropertyAttribute(
755 nCurrentValueAttributeNamespaceKey,
756 pCurrentValueAttributeName,
757 pCurrentValuePropertyName
762 if (!pValuePropertyName.isEmpty() && (CCAFlags::Value & m_nIncludeCommon))
764 static const OUString pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Value);
765 static const sal_uInt16 nValueAttributeNamespaceKey = OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Value);
766 exportGenericPropertyAttribute(
767 nValueAttributeNamespaceKey,
768 pValueAttributeName,
769 pValuePropertyName);
772 OSL_ENSURE((pValuePropertyName.isEmpty()) == (CCAFlags::NONE == (CCAFlags::Value & m_nIncludeCommon)),
773 "OControlExport::exportCommonControlAttributes: no property found for the value attribute!");
774 OSL_ENSURE((pCurrentValuePropertyName.isEmpty()) == (CCAFlags::NONE == (CCAFlags::CurrentValue & m_nIncludeCommon)),
775 "OControlExport::exportCommonControlAttributes: no property found for the current-value attribute!");
777 #if OSL_DEBUG_LEVEL > 0
778 // reset the bit for later checking
779 m_nIncludeCommon = m_nIncludeCommon & ~CCAFlags(CCAFlags::CurrentValue | CCAFlags::Value);
780 #endif
783 OSL_ENSURE(CCAFlags::NONE == m_nIncludeCommon,
784 "OControlExport::exportCommonControlAttributes: forgot some flags!");
785 // in the dbg_util version, we should have removed every bit we handled from the mask, so it should
786 // be 0 now ...
789 void OControlExport::exportDatabaseAttributes()
791 #if OSL_DEBUG_LEVEL > 0
792 DAFlags nIncludeDatabase = m_nIncludeDatabase;
793 #endif
794 // the only string property: DataField
795 if (DAFlags::DataField & m_nIncludeDatabase)
797 exportStringPropertyAttribute(
798 OAttributeMetaData::getDatabaseAttributeNamespace(),
799 OAttributeMetaData::getDatabaseAttributeName(DAFlags::DataField),
800 PROPERTY_DATAFIELD);
801 RESET_BIT( nIncludeDatabase, DAFlags::DataField );
804 // InputRequired
805 if ( DAFlags::InputRequired & m_nIncludeDatabase )
807 exportBooleanPropertyAttribute(
808 OAttributeMetaData::getDatabaseAttributeNamespace(),
809 OAttributeMetaData::getDatabaseAttributeName( DAFlags::InputRequired ),
810 PROPERTY_INPUT_REQUIRED,
811 BoolAttrFlags::DefaultFalse | BoolAttrFlags::DefaultVoid
813 RESET_BIT( nIncludeDatabase, DAFlags::InputRequired );
816 // the only int16 property: BoundColumn
817 if (DAFlags::BoundColumn & m_nIncludeDatabase)
819 exportInt16PropertyAttribute(
820 OAttributeMetaData::getDatabaseAttributeNamespace(),
821 OAttributeMetaData::getDatabaseAttributeName(DAFlags::BoundColumn),
822 PROPERTY_BOUNDCOLUMN,
824 true);
825 RESET_BIT( nIncludeDatabase, DAFlags::BoundColumn );
828 // ConvertEmptyToNull
829 if (DAFlags::ConvertEmpty & m_nIncludeDatabase)
831 exportBooleanPropertyAttribute(
832 OAttributeMetaData::getDatabaseAttributeNamespace(),
833 OAttributeMetaData::getDatabaseAttributeName(DAFlags::ConvertEmpty),
834 PROPERTY_EMPTY_IS_NULL,
835 BoolAttrFlags::DefaultFalse
837 RESET_BIT( nIncludeDatabase, DAFlags::ConvertEmpty );
840 // the only enum property: ListSourceType
841 if (DAFlags::ListSource_TYPE & m_nIncludeDatabase)
843 exportEnumPropertyAttribute(
844 OAttributeMetaData::getDatabaseAttributeNamespace(),
845 OAttributeMetaData::getDatabaseAttributeName(DAFlags::ListSource_TYPE),
846 PROPERTY_LISTSOURCETYPE,
847 aListSourceTypeMap,
848 ListSourceType_VALUELIST
850 RESET_BIT( nIncludeDatabase, DAFlags::ListSource_TYPE );
853 if (m_nIncludeDatabase & DAFlags::ListSource)
855 exportListSourceAsAttribute();
856 RESET_BIT( nIncludeDatabase, DAFlags::ListSource );
859 #if OSL_DEBUG_LEVEL > 0
860 OSL_ENSURE(DAFlags::NONE == nIncludeDatabase,
861 "OControlExport::exportDatabaseAttributes: forgot some flags!");
862 // in the dbg_util version, we should have removed every bit we handled from the mask, so it should
863 // be 0 now ...
864 #endif
867 void OControlExport::exportBindingAttributes()
869 #if OSL_DEBUG_LEVEL > 0
870 BAFlags nIncludeBinding = m_nIncludeBindings;
871 #endif
873 if ( m_nIncludeBindings & BAFlags::LinkedCell )
875 exportCellBindingAttributes( bool(m_nIncludeBindings & BAFlags::ListLinkingType) );
876 #if OSL_DEBUG_LEVEL > 0
877 // reset the bit for later checking
878 nIncludeBinding = nIncludeBinding & ~BAFlags( BAFlags::LinkedCell | BAFlags::ListLinkingType );
879 #endif
882 if ( m_nIncludeBindings & BAFlags::ListCellRange )
884 exportCellListSourceRange();
885 #if OSL_DEBUG_LEVEL > 0
886 // reset the bit for later checking
887 nIncludeBinding = nIncludeBinding & ~BAFlags::ListCellRange;
888 #endif
891 if ( m_nIncludeBindings & BAFlags::XFormsBind )
893 exportXFormsBindAttributes();
894 #if OSL_DEBUG_LEVEL > 0
895 // reset the bit for later checking
896 nIncludeBinding = nIncludeBinding & ~BAFlags::XFormsBind;
897 #endif
900 if ( m_nIncludeBindings & BAFlags::XFormsListBind )
902 exportXFormsListAttributes();
903 #if OSL_DEBUG_LEVEL > 0
904 // reset the bit for later checking
905 nIncludeBinding = nIncludeBinding & ~BAFlags::XFormsListBind;
906 #endif
909 if ( m_nIncludeBindings & BAFlags::XFormsSubmission )
911 exportXFormsSubmissionAttributes();
912 #if OSL_DEBUG_LEVEL > 0
913 // reset the bit for later checking
914 nIncludeBinding = nIncludeBinding & ~BAFlags::XFormsSubmission;
915 #endif
918 #if OSL_DEBUG_LEVEL > 0
919 OSL_ENSURE( BAFlags::NONE == nIncludeBinding,
920 "OControlExport::exportBindingAttributes: forgot some flags!");
921 // in the debug version, we should have removed every bit we handled from the mask, so it should
922 // be 0 now ...
923 #endif
926 void OControlExport::exportSpecialAttributes()
928 sal_Int32 i=0;
930 // the boolean properties
932 static const SCAFlags nBooleanPropertyAttributeIds[] =
933 { // attribute flags
934 SCAFlags::Validation, SCAFlags::MultiLine, SCAFlags::AutoCompletion, SCAFlags::Multiple, SCAFlags::DefaultButton, SCAFlags::IsTristate,
935 SCAFlags::Toggle, SCAFlags::FocusOnClick
937 static const rtl::OUStringConstExpr pBooleanPropertyNames[] =
938 { // property names
939 PROPERTY_STRICTFORMAT, PROPERTY_MULTILINE,
940 PROPERTY_AUTOCOMPLETE,
941 PROPERTY_MULTISELECTION,
942 PROPERTY_DEFAULTBUTTON, PROPERTY_TRISTATE,
943 PROPERTY_TOGGLE, PROPERTY_FOCUS_ON_CLICK
945 static const sal_Int32 nIdCount = std::size(nBooleanPropertyAttributeIds);
946 #if OSL_DEBUG_LEVEL > 0
947 static const sal_Int32 nNameCount = std::size(pBooleanPropertyNames);
948 OSL_ENSURE((nIdCount == nNameCount),
949 "OControlExport::exportSpecialAttributes: somebody tampered with the maps (1)!");
950 #endif
951 const SCAFlags* pAttributeId = nBooleanPropertyAttributeIds;
952 for ( i = 0; i < nIdCount; ++i, ++pAttributeId )
954 if ( *pAttributeId & m_nIncludeSpecial)
956 exportBooleanPropertyAttribute(
957 OAttributeMetaData::getSpecialAttributeNamespace( *pAttributeId ),
958 OAttributeMetaData::getSpecialAttributeName( *pAttributeId ),
959 pBooleanPropertyNames[i],
960 ( *pAttributeId == SCAFlags::FocusOnClick ) ? BoolAttrFlags::DefaultTrue : BoolAttrFlags::DefaultFalse
962 #if OSL_DEBUG_LEVEL > 0
963 // reset the bit for later checking
964 m_nIncludeSpecial = m_nIncludeSpecial & ~*pAttributeId;
965 #endif
970 // the integer properties
972 static const SCAFlags nIntegerPropertyAttributeIds[] =
973 { // attribute flags
974 SCAFlags::PageStepSize
976 static const rtl::OUStringConstExpr pIntegerPropertyNames[] =
977 { // property names
978 PROPERTY_BLOCK_INCREMENT
980 static const sal_Int32 nIntegerPropertyAttrDefaults[] =
981 { // attribute defaults (XML defaults, not runtime defaults!)
985 static const sal_Int32 nIdCount = std::size( nIntegerPropertyAttributeIds );
986 #if OSL_DEBUG_LEVEL > 0
987 static const sal_Int32 nNameCount = std::size( pIntegerPropertyNames );
988 OSL_ENSURE( ( nIdCount == nNameCount ),
989 "OControlExport::exportSpecialAttributes: somebody tampered with the maps (2)!" );
990 static const sal_Int32 nDefaultCount = std::size( nIntegerPropertyAttrDefaults );
991 OSL_ENSURE( ( nIdCount == nDefaultCount ),
992 "OControlExport::exportSpecialAttributes: somebody tampered with the maps (3)!" );
993 #endif
994 for ( i = 0; i < nIdCount; ++i )
995 if ( nIntegerPropertyAttributeIds[i] & m_nIncludeSpecial )
997 exportInt32PropertyAttribute(
998 OAttributeMetaData::getSpecialAttributeNamespace( nIntegerPropertyAttributeIds[i] ),
999 OAttributeMetaData::getSpecialAttributeName( nIntegerPropertyAttributeIds[i] ),
1000 pIntegerPropertyNames[i],
1001 nIntegerPropertyAttrDefaults[i]
1003 #if OSL_DEBUG_LEVEL > 0
1004 // reset the bit for later checking
1005 m_nIncludeSpecial = m_nIncludeSpecial & ~nIntegerPropertyAttributeIds[i];
1006 #endif
1009 if ( SCAFlags::StepSize & m_nIncludeSpecial )
1011 OUString sPropertyName;
1012 if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) )
1013 sPropertyName = PROPERTY_LINE_INCREMENT;
1014 else if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) )
1015 sPropertyName = PROPERTY_SPIN_INCREMENT;
1016 else
1017 OSL_FAIL( "OControlExport::exportSpecialAttributes: not property which can be mapped to step-size attribute!" );
1019 if ( !sPropertyName.isEmpty() )
1020 exportInt32PropertyAttribute(
1021 OAttributeMetaData::getSpecialAttributeNamespace( SCAFlags::StepSize ),
1022 OAttributeMetaData::getSpecialAttributeName( SCAFlags::StepSize ),
1023 sPropertyName,
1027 #if OSL_DEBUG_LEVEL > 0
1028 // reset the bit for later checking
1029 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags::StepSize;
1030 #endif
1035 // the enum properties
1037 if (SCAFlags::State & m_nIncludeSpecial)
1039 exportEnumPropertyAttribute(
1040 OAttributeMetaData::getSpecialAttributeNamespace(SCAFlags::State),
1041 OAttributeMetaData::getSpecialAttributeName(SCAFlags::State),
1042 PROPERTY_DEFAULT_STATE,
1043 aCheckStateMap,
1044 TRISTATE_FALSE);
1045 #if OSL_DEBUG_LEVEL > 0
1046 // reset the bit for later checking
1047 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags::State;
1048 #endif
1051 if (SCAFlags::CurrentState & m_nIncludeSpecial)
1053 exportEnumPropertyAttribute(
1054 OAttributeMetaData::getSpecialAttributeNamespace(SCAFlags::CurrentState),
1055 OAttributeMetaData::getSpecialAttributeName(SCAFlags::CurrentState),
1056 PROPERTY_STATE,
1057 aCheckStateMap,
1058 TRISTATE_FALSE);
1059 #if OSL_DEBUG_LEVEL > 0
1060 // reset the bit for later checking
1061 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags::CurrentState;
1062 #endif
1066 // some properties which require a special handling
1067 // the repeat delay
1069 if ( m_nIncludeSpecial & SCAFlags::RepeatDelay )
1071 DBG_CHECK_PROPERTY( PROPERTY_REPEAT_DELAY, sal_Int32 );
1073 sal_Int32 nRepeatDelay = 0;
1074 m_xProps->getPropertyValue( PROPERTY_REPEAT_DELAY ) >>= nRepeatDelay;
1075 tools::Time aTime( tools::Time::SYSTEM );
1076 aTime.MakeTimeFromMS( nRepeatDelay );
1077 util::Duration aDuration;
1078 aDuration.Hours = aTime.GetHour();
1079 aDuration.Minutes = aTime.GetMin();
1080 aDuration.Seconds = aTime.GetSec();
1081 aDuration.NanoSeconds = (nRepeatDelay % 1000) * 1000000;
1083 OUStringBuffer buf;
1084 ::sax::Converter::convertDuration(buf, aDuration);
1085 AddAttribute(OAttributeMetaData::getSpecialAttributeNamespace( SCAFlags::RepeatDelay )
1086 ,OAttributeMetaData::getSpecialAttributeName( SCAFlags::RepeatDelay )
1087 ,buf.makeStringAndClear());
1089 exportedProperty( PROPERTY_REPEAT_DELAY );
1091 #if OSL_DEBUG_LEVEL > 0
1092 // reset the bit for later checking
1093 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags::RepeatDelay;
1094 #endif
1098 // the EchoChar property needs special handling, cause it's a Int16, but must be stored as one-character-string
1100 if (SCAFlags::EchoChar & m_nIncludeSpecial)
1102 DBG_CHECK_PROPERTY( PROPERTY_ECHO_CHAR, sal_Int16 );
1103 sal_Int16 nValue(0);
1104 m_xProps->getPropertyValue(PROPERTY_ECHO_CHAR) >>= nValue;
1105 if (nValue)
1107 OUString sCharacter(reinterpret_cast<const sal_Unicode*>(&nValue), 1);
1108 AddAttribute(
1109 OAttributeMetaData::getSpecialAttributeNamespace(SCAFlags::EchoChar),
1110 OAttributeMetaData::getSpecialAttributeName(SCAFlags::EchoChar),
1111 sCharacter);
1113 exportedProperty(PROPERTY_ECHO_CHAR);
1114 #if OSL_DEBUG_LEVEL > 0
1115 // reset the bit for later checking
1116 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags::EchoChar;
1117 #endif
1121 // the string properties
1123 static const SCAFlags nStringPropertyAttributeIds[] =
1124 { // attribute flags
1125 SCAFlags::GroupName
1127 static const rtl::OUStringConstExpr pStringPropertyNames[] =
1128 { // property names
1129 PROPERTY_GROUP_NAME
1132 static const sal_Int32 nIdCount = std::size( nStringPropertyAttributeIds );
1133 #if OSL_DEBUG_LEVEL > 0
1134 static const sal_Int32 nNameCount = std::size( pStringPropertyNames );
1135 OSL_ENSURE( ( nIdCount == nNameCount ),
1136 "OControlExport::exportSpecialAttributes: somebody tampered with the maps (2)!" );
1137 #endif
1138 for ( i = 0; i < nIdCount; ++i )
1139 if ( nStringPropertyAttributeIds[i] & m_nIncludeSpecial )
1141 exportStringPropertyAttribute(
1142 OAttributeMetaData::getSpecialAttributeNamespace( nStringPropertyAttributeIds[i] ),
1143 OAttributeMetaData::getSpecialAttributeName( nStringPropertyAttributeIds[i] ),
1144 OUString(pStringPropertyNames[i])
1146 #if OSL_DEBUG_LEVEL > 0
1147 // reset the bit for later checking
1148 m_nIncludeSpecial = m_nIncludeSpecial & ~nStringPropertyAttributeIds[i];
1149 #endif
1153 if ((SCAFlags::MinValue | SCAFlags::MaxValue) & m_nIncludeSpecial)
1155 // need to export the min value and the max value as attributes
1156 // It depends on the real type (FormComponentType) of the control, which properties hold these
1157 // values
1158 OUString pMinValuePropertyName;
1159 OUString pMaxValuePropertyName;
1160 getValueLimitPropertyNames(m_nClassId, pMinValuePropertyName, pMaxValuePropertyName);
1162 OSL_ENSURE((pMinValuePropertyName.isEmpty()) == (SCAFlags::NONE == (SCAFlags::MinValue & m_nIncludeSpecial)),
1163 "OControlExport::exportCommonControlAttributes: no property found for the min value attribute!");
1164 OSL_ENSURE((pMaxValuePropertyName.isEmpty()) == (SCAFlags::NONE == (SCAFlags::MaxValue & m_nIncludeSpecial)),
1165 "OControlExport::exportCommonControlAttributes: no property found for the max value attribute!");
1167 // add the two attributes
1168 static const OUString pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCAFlags::MinValue);
1169 static const OUString pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCAFlags::MaxValue);
1170 static const sal_uInt16 nMinValueNamespaceKey = OAttributeMetaData::getSpecialAttributeNamespace(SCAFlags::MinValue);
1171 static const sal_uInt16 nMaxValueNamespaceKey = OAttributeMetaData::getSpecialAttributeNamespace(SCAFlags::MaxValue);
1173 if (!pMinValuePropertyName.isEmpty() && (SCAFlags::MinValue & m_nIncludeSpecial))
1174 exportGenericPropertyAttribute(
1175 nMinValueNamespaceKey,
1176 pMinValueAttributeName,
1177 pMinValuePropertyName);
1179 if (!pMaxValuePropertyName.isEmpty() && (SCAFlags::MaxValue & m_nIncludeSpecial))
1180 exportGenericPropertyAttribute(
1181 nMaxValueNamespaceKey,
1182 pMaxValueAttributeName,
1183 pMaxValuePropertyName);
1184 #if OSL_DEBUG_LEVEL > 0
1185 // reset the bit for later checking
1186 m_nIncludeSpecial = m_nIncludeSpecial & ~SCAFlags(SCAFlags::MinValue | SCAFlags::MaxValue);
1187 #endif
1190 if ( SCAFlags::ImagePosition & m_nIncludeSpecial )
1192 exportImagePositionAttributes();
1193 RESET_BIT( m_nIncludeSpecial, SCAFlags::ImagePosition );
1196 OSL_ENSURE(SCAFlags::NONE == m_nIncludeSpecial,
1197 "OControlExport::exportSpecialAttributes: forgot some flags!");
1198 // in the dbg_util version, we should have removed every bit we handled from the mask, so it should
1199 // be 0 now ...
1202 OUString OControlExport::getScalarListSourceValue() const
1204 OUString sListSource;
1205 Any aListSource = m_xProps->getPropertyValue( PROPERTY_LISTSOURCE );
1206 if ( !( aListSource >>= sListSource ) )
1208 Sequence< OUString > aListSourceSequence;
1209 aListSource >>= aListSourceSequence;
1210 if ( aListSourceSequence.hasElements() )
1211 sListSource = aListSourceSequence[ 0 ];
1213 return sListSource;
1216 void OControlExport::exportListSourceAsAttribute()
1218 // DAFlags::ListSource needs some special handling
1219 DBG_CHECK_PROPERTY_NO_TYPE( PROPERTY_LISTSOURCE );
1221 OUString sListSource = getScalarListSourceValue();
1222 if ( !sListSource.isEmpty() )
1223 { // the ListSource property needs to be exported as attribute, and it is not empty
1224 AddAttribute(
1225 OAttributeMetaData::getDatabaseAttributeNamespace(),
1226 OAttributeMetaData::getDatabaseAttributeName(DAFlags::ListSource),
1227 sListSource);
1230 exportedProperty( PROPERTY_LISTSOURCE );
1233 void OControlExport::getSequenceInt16PropertyAsSet(const OUString& _rPropertyName, Int16Set& _rOut)
1235 Sequence< sal_Int16 > aValueSequence;
1236 DBG_CHECK_PROPERTY(_rPropertyName, Sequence< sal_Int16 >);
1237 m_xProps->getPropertyValue(_rPropertyName) >>= aValueSequence;
1239 for (const auto& rValue : std::as_const(aValueSequence))
1240 _rOut.insert(rValue);
1243 void OControlExport::exportListSourceAsElements()
1245 // the string lists
1246 Sequence< OUString > aItems, aValues;
1247 DBG_CHECK_PROPERTY( PROPERTY_STRING_ITEM_LIST, Sequence< OUString > );
1248 m_xProps->getPropertyValue(PROPERTY_STRING_ITEM_LIST) >>= aItems;
1250 DBG_CHECK_PROPERTY( PROPERTY_LISTSOURCE, Sequence< OUString > );
1251 if ( DAFlags::NONE == ( m_nIncludeDatabase & DAFlags::ListSource ) )
1252 m_xProps->getPropertyValue(PROPERTY_LISTSOURCE) >>= aValues;
1253 // if we exported the list source as attribute, we do not repeat it as sub elements
1255 // the selection lists
1256 Int16Set aSelection, aDefaultSelection;
1257 getSequenceInt16PropertyAsSet(PROPERTY_SELECT_SEQ, aSelection);
1258 getSequenceInt16PropertyAsSet(PROPERTY_DEFAULT_SELECT_SEQ, aDefaultSelection);
1260 // the string for "true"
1261 OUString sTrue;
1262 OUStringBuffer sBuffer;
1263 ::sax::Converter::convertBool(sBuffer, true);
1264 sTrue = sBuffer.makeStringAndClear();
1266 // loop through both lists ('til the maximum of both lengths)
1267 const OUString* pItems = aItems.getConstArray();
1268 const OUString* pValues = aValues.getConstArray();
1270 sal_Int32 nItems = aItems.getLength();
1271 sal_Int32 nValues = aValues.getLength();
1273 sal_Int16 nMaxLen = static_cast<sal_Int16>(std::max(nItems, nValues));
1275 for (sal_Int16 i=0; i<nMaxLen; ++i )
1277 m_rContext.getGlobalContext().ClearAttrList();
1278 if (i < nItems)
1280 // there is an item at this position
1281 AddAttribute(
1282 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Label),
1283 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Label),
1284 *pItems);
1285 ++pItems;
1287 if (i < nValues)
1289 // there is a value at this position
1290 AddAttribute(
1291 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Value),
1292 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Value),
1293 *pValues);
1294 ++pValues;
1297 Int16Set::const_iterator aSelectedPos = aSelection.find(i);
1298 if (aSelection.end() != aSelectedPos)
1299 { // the item at this position is selected
1300 AddAttribute(
1301 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::CurrentSelected),
1302 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentSelected),
1303 sTrue
1305 aSelection.erase(aSelectedPos);
1308 Int16Set::const_iterator aDefaultSelectedPos = aDefaultSelection.find(i);
1309 if (aDefaultSelection.end() != aDefaultSelectedPos)
1310 { // the item at this position is selected as default
1311 AddAttribute(
1312 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Selected),
1313 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Selected),
1314 sTrue
1316 aDefaultSelection.erase(aDefaultSelectedPos);
1318 SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "option", true, true);
1321 // There may be more "selected" or "default-selected" items than there are in the lists in real,
1322 // so we need to store some additional "form:option" items which have no name and no label, but
1323 // one or both of the selected flags.
1324 // 21.05.2001 - 85388 - frank.schoenheit@germany.sun.com
1326 if (aSelection.empty() && aDefaultSelection.empty())
1327 return;
1329 sal_Int16 nLastSelected = -1;
1330 if ( !aSelection.empty() )
1331 nLastSelected = *(--aSelection.end());
1333 sal_Int16 nLastDefaultSelected = -1;
1334 if ( !aDefaultSelection.empty() )
1335 nLastDefaultSelected = *(--aDefaultSelection.end());
1337 // the maximum element in both sets
1338 sal_Int16 nLastReferredEntry = std::max(nLastSelected, nLastDefaultSelected);
1339 OSL_ENSURE(nLastReferredEntry >= nMaxLen, "OControlExport::exportListSourceAsElements: inconsistence!");
1340 // if the maximum (selected or default selected) entry number is less than the maximum item count
1341 // in both lists, the entry number should have been removed from the set
1343 for (sal_Int16 i=nMaxLen; i<=nLastReferredEntry; ++i)
1345 if (aSelection.end() != aSelection.find(i))
1346 { // the (not existent) item at this position is selected
1347 AddAttribute(
1348 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::CurrentSelected),
1349 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentSelected),
1350 sTrue
1354 if (aDefaultSelection.end() != aDefaultSelection.find(i))
1355 { // the (not existent) item at this position is selected as default
1356 AddAttribute(
1357 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Selected),
1358 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Selected),
1359 sTrue
1362 SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, "option", true, true);
1366 void OControlExport::implStartElement(const char* _pName)
1368 // before we let the base class start it's outer element, we add a wrapper element
1369 const char *pOuterElementName = getOuterXMLElementName();
1370 if (pOuterElementName)
1371 m_pOuterElement = std::make_unique<SvXMLElementExport>(
1372 m_rContext.getGlobalContext(),
1373 XML_NAMESPACE_FORM,
1374 pOuterElementName, true,
1375 true);
1377 // add the attributes for the inner element
1378 exportInnerAttributes();
1380 // and start the inner element
1381 OElementExport::implStartElement(_pName);
1384 void OControlExport::implEndElement()
1386 // end the inner element
1387 OElementExport::implEndElement();
1389 // end the outer element if it exists
1390 m_pOuterElement.reset();
1393 const char* OControlExport::getOuterXMLElementName() const
1395 return nullptr;
1398 const char* OControlExport::getXMLElementName() const
1400 return getElementName(m_eType);
1403 void OControlExport::examine()
1405 OSL_ENSURE( ( m_nIncludeCommon == CCAFlags::NONE ) && ( m_nIncludeSpecial == SCAFlags::NONE ) && ( m_nIncludeDatabase == DAFlags::NONE )
1406 && ( m_nIncludeEvents == EAFlags::NONE ) && ( m_nIncludeBindings == BAFlags::NONE),
1407 "OControlExport::examine: called me twice? Not initialized?" );
1409 // get the class id to decide which kind of element we need in the XML stream
1410 m_nClassId = FormComponentType::CONTROL;
1411 DBG_CHECK_PROPERTY( PROPERTY_CLASSID, sal_Int16 );
1412 m_xProps->getPropertyValue(PROPERTY_CLASSID) >>= m_nClassId;
1413 bool knownType = false;
1414 switch (m_nClassId)
1416 case FormComponentType::DATEFIELD:
1417 m_eType = DATE;
1418 knownType = true;
1419 [[fallthrough]];
1420 case FormComponentType::TIMEFIELD:
1421 if ( !knownType )
1423 m_eType = TIME;
1424 knownType = true;
1426 m_nIncludeSpecial |= SCAFlags::Validation;
1427 [[fallthrough]];
1428 case FormComponentType::NUMERICFIELD:
1429 case FormComponentType::CURRENCYFIELD:
1430 case FormComponentType::PATTERNFIELD:
1431 if ( !knownType )
1433 m_eType = FORMATTED_TEXT;
1434 knownType = true;
1436 [[fallthrough]];
1437 case FormComponentType::TEXTFIELD:
1438 { // it's some kind of edit. To know which type we need further investigation
1440 if ( !knownType )
1442 // check if it's a formatted field
1443 if (m_xPropertyInfo->hasPropertyByName(PROPERTY_FORMATKEY))
1445 m_eType = FORMATTED_TEXT;
1447 else
1449 // all other controls are represented by an ordinary edit control, but which XML control type
1450 // it is depends on the current values of some properties
1452 // if the EchoChar string is not empty, it is a password field
1453 sal_Int16 nEchoChar = 0;
1454 if (m_xPropertyInfo->hasPropertyByName(PROPERTY_ECHOCHAR))
1455 // grid columns do not have this property...
1456 m_xProps->getPropertyValue(PROPERTY_ECHOCHAR) >>= nEchoChar;
1457 if (nEchoChar)
1459 m_eType = PASSWORD;
1460 m_nIncludeSpecial |= SCAFlags::EchoChar;
1462 else
1464 // if the MultiLine property is sal_True, it is a TextArea
1465 bool bMultiLine = false;
1466 if (m_xPropertyInfo->hasPropertyByName(PROPERTY_MULTILINE))
1467 // grid columns do not have this property...
1468 bMultiLine = ::cppu::any2bool(m_xProps->getPropertyValue(PROPERTY_MULTILINE));
1470 if ( bMultiLine )
1471 m_eType = TEXT_AREA;
1472 else
1473 // the only case left is represented by a Text element
1474 m_eType = TEXT;
1479 // attributes which are common to all the types:
1480 // common attributes
1481 m_nIncludeCommon =
1482 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled |
1483 CCAFlags::Printable | CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title;
1485 if ( ( m_nClassId != FormComponentType::DATEFIELD )
1486 && ( m_nClassId != FormComponentType::TIMEFIELD )
1488 // date and time field values are handled differently nowadays
1489 m_nIncludeCommon |= CCAFlags::Value;
1491 // database attributes
1492 m_nIncludeDatabase = DAFlags::DataField | DAFlags::InputRequired;
1494 // event attributes
1495 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnChange | EAFlags::OnSelect;
1497 // only text and pattern fields have a ConvertEmptyToNull property
1498 if ( ( m_nClassId == FormComponentType::TEXTFIELD )
1499 || ( m_nClassId == FormComponentType::PATTERNFIELD )
1501 m_nIncludeDatabase |= DAFlags::ConvertEmpty;
1503 // all controls but the file control fields have a readonly property
1504 if ( m_nClassId != FormComponentType::FILECONTROL )
1505 m_nIncludeCommon |= CCAFlags::ReadOnly;
1507 // a text field has a max text len
1508 if ( m_nClassId == FormComponentType::TEXTFIELD )
1509 m_nIncludeCommon |= CCAFlags::MaxLength;
1511 // max and min values and validation:
1512 if (FORMATTED_TEXT == m_eType)
1513 { // in general all controls represented as formatted-text have these props
1514 if ( FormComponentType::PATTERNFIELD != m_nClassId ) // except the PatternField
1515 m_nIncludeSpecial |= SCAFlags::MaxValue | SCAFlags::MinValue;
1517 if (FormComponentType::TEXTFIELD != m_nClassId)
1518 // and the FormattedField does not have a validation flag
1519 m_nIncludeSpecial |= SCAFlags::Validation;
1522 // if it's not a password field or rich text control, the CurrentValue needs to be stored, too
1523 if ( ( PASSWORD != m_eType )
1524 && ( DATE != m_eType )
1525 && ( TIME != m_eType )
1528 m_nIncludeCommon |= CCAFlags::CurrentValue;
1531 break;
1533 case FormComponentType::FILECONTROL:
1534 m_eType = FILE;
1535 m_nIncludeCommon =
1536 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::CurrentValue | CCAFlags::Disabled |
1537 CCAFlags::Printable | CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title |
1538 CCAFlags::Value;
1539 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnChange | EAFlags::OnSelect;
1540 break;
1542 case FormComponentType::FIXEDTEXT:
1543 m_eType = FIXED_TEXT;
1544 m_nIncludeCommon =
1545 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Label |
1546 CCAFlags::Printable | CCAFlags::Title | CCAFlags::For;
1547 m_nIncludeSpecial = SCAFlags::MultiLine;
1548 m_nIncludeEvents = EAFlags::ControlEvents;
1549 break;
1551 case FormComponentType::COMBOBOX:
1552 m_eType = COMBOBOX;
1553 m_nIncludeCommon =
1554 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::CurrentValue |
1555 CCAFlags::Disabled | CCAFlags::Dropdown | CCAFlags::MaxLength | CCAFlags::Printable | CCAFlags::ReadOnly | CCAFlags::Size |
1556 CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title | CCAFlags::Value;
1557 m_nIncludeSpecial = SCAFlags::AutoCompletion;
1558 m_nIncludeDatabase = DAFlags::ConvertEmpty | DAFlags::DataField | DAFlags::InputRequired | DAFlags::ListSource | DAFlags::ListSource_TYPE;
1559 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnChange | EAFlags::OnSelect;
1560 break;
1562 case FormComponentType::LISTBOX:
1563 m_eType = LISTBOX;
1564 m_nIncludeCommon =
1565 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Dropdown |
1566 CCAFlags::Printable | CCAFlags::Size | CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title;
1567 m_nIncludeSpecial = SCAFlags::Multiple;
1568 m_nIncludeDatabase = DAFlags::BoundColumn | DAFlags::DataField | DAFlags::InputRequired | DAFlags::ListSource_TYPE;
1569 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnChange | EAFlags::OnClick | EAFlags::OnDoubleClick;
1570 // check if we need to export the ListSource as attribute
1572 // for a list box, if the ListSourceType is VALUE_LIST, no ListSource is stored, but instead
1573 // a sequence of pairs which is build from the StringItemList and the ValueList
1574 ListSourceType eListSourceType = ListSourceType_VALUELIST;
1575 bool bSuccess =
1576 m_xProps->getPropertyValue(PROPERTY_LISTSOURCETYPE) >>= eListSourceType;
1577 OSL_ENSURE(bSuccess, "OControlExport::examineControl: could not retrieve the ListSourceType!");
1578 if (ListSourceType_VALUELIST != eListSourceType)
1580 m_nIncludeDatabase |= DAFlags::ListSource;
1584 break;
1586 case FormComponentType::COMMANDBUTTON:
1587 m_eType = BUTTON;
1588 m_nIncludeCommon |= CCAFlags::TabStop | CCAFlags::Label;
1589 m_nIncludeSpecial = SCAFlags::DefaultButton | SCAFlags::Toggle | SCAFlags::FocusOnClick | SCAFlags::ImagePosition | SCAFlags::RepeatDelay;
1590 [[fallthrough]];
1591 case FormComponentType::IMAGEBUTTON:
1592 if (BUTTON != m_eType)
1594 // not coming from the previous case
1595 m_eType = IMAGE;
1597 m_nIncludeCommon |=
1598 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::ButtonType | CCAFlags::Disabled |
1599 CCAFlags::ImageData | CCAFlags::Printable | CCAFlags::TabIndex | CCAFlags::TargetFrame |
1600 CCAFlags::TargetLocation | CCAFlags::Title;
1601 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnClick | EAFlags::OnDoubleClick;
1602 break;
1604 case FormComponentType::CHECKBOX:
1605 m_eType = CHECKBOX;
1606 m_nIncludeSpecial = SCAFlags::CurrentState | SCAFlags::IsTristate | SCAFlags::State;
1607 [[fallthrough]];
1608 case FormComponentType::RADIOBUTTON:
1609 m_nIncludeCommon =
1610 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Label | CCAFlags::Printable |
1611 CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title | CCAFlags::Value | CCAFlags::VisualEffect;
1612 if (CHECKBOX != m_eType)
1613 { // not coming from the previous case
1614 m_eType = RADIO;
1615 m_nIncludeCommon |= CCAFlags::CurrentSelected | CCAFlags::Selected;
1617 if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_IMAGE_POSITION ) )
1618 m_nIncludeSpecial |= SCAFlags::ImagePosition;
1619 if ( m_xPropertyInfo->hasPropertyByName( PROPERTY_GROUP_NAME ) )
1620 m_nIncludeSpecial |= SCAFlags::GroupName;
1621 m_nIncludeDatabase = DAFlags::DataField | DAFlags::InputRequired;
1622 m_nIncludeEvents = EAFlags::ControlEvents | EAFlags::OnChange;
1623 break;
1625 case FormComponentType::GROUPBOX:
1626 m_eType = FRAME;
1627 m_nIncludeCommon =
1628 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Label |
1629 CCAFlags::Printable | CCAFlags::Title | CCAFlags::For;
1630 m_nIncludeEvents = EAFlags::ControlEvents;
1631 break;
1633 case FormComponentType::IMAGECONTROL:
1634 m_eType = IMAGE_FRAME;
1635 m_nIncludeCommon =
1636 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::ImageData |
1637 CCAFlags::Printable | CCAFlags::ReadOnly | CCAFlags::Title;
1638 m_nIncludeDatabase = DAFlags::DataField | DAFlags::InputRequired;
1639 m_nIncludeEvents = EAFlags::ControlEvents;
1640 break;
1642 case FormComponentType::HIDDENCONTROL:
1643 m_eType = HIDDEN;
1644 m_nIncludeCommon =
1645 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Value;
1646 break;
1648 case FormComponentType::GRIDCONTROL:
1649 m_eType = GRID;
1650 m_nIncludeCommon =
1651 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Printable |
1652 CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Title;
1653 m_nIncludeEvents = EAFlags::ControlEvents;
1654 break;
1656 case FormComponentType::SCROLLBAR:
1657 case FormComponentType::SPINBUTTON:
1658 m_eType = VALUERANGE;
1659 m_nIncludeCommon =
1660 CCAFlags::Name | CCAFlags::ServiceName | CCAFlags::Disabled | CCAFlags::Printable |
1661 CCAFlags::Title | CCAFlags::CurrentValue | CCAFlags::Value | CCAFlags::Orientation;
1662 m_nIncludeSpecial = SCAFlags::MaxValue | SCAFlags::StepSize | SCAFlags::MinValue | SCAFlags::RepeatDelay;
1664 if ( m_nClassId == FormComponentType::SCROLLBAR )
1665 m_nIncludeSpecial |= SCAFlags::PageStepSize ;
1667 m_nIncludeEvents = EAFlags::ControlEvents;
1668 break;
1670 default:
1671 OSL_FAIL("OControlExport::examineControl: unknown control type (class id)!");
1672 [[fallthrough]];
1674 case FormComponentType::NAVIGATIONBAR:
1675 // TODO: should we have an own file format for this?
1676 // NO break
1678 case FormComponentType::CONTROL:
1679 m_eType = GENERIC_CONTROL;
1680 // unknown control type
1681 m_nIncludeCommon = CCAFlags::Name | CCAFlags::ServiceName;
1682 // at least a name should be there, 'cause without a name the control could never have been
1683 // inserted into its parent container
1684 // In addition, the service name is absolutely necessary to create the control upon reading.
1685 m_nIncludeEvents = EAFlags::ControlEvents;
1686 // we always should be able to export events - this is not control type dependent
1687 break;
1690 // in general, all control types need to export the control id
1691 m_nIncludeCommon |= CCAFlags::ControlId;
1693 // is it a control bound to a calc cell?
1694 if ( FormCellBindingHelper::livesInSpreadsheetDocument( m_xProps ) )
1696 FormCellBindingHelper aHelper( m_xProps, nullptr );
1698 if ( FormCellBindingHelper::isCellBinding( aHelper.getCurrentBinding( ) ) )
1700 m_nIncludeBindings |= BAFlags::LinkedCell;
1701 if ( m_nClassId == FormComponentType::LISTBOX )
1702 m_nIncludeBindings |= BAFlags::ListLinkingType;
1706 // is it a list-like control which uses a calc cell range as list source?
1708 if ( FormCellBindingHelper::isCellRangeListSource( aHelper.getCurrentListSource( ) ) )
1709 m_nIncludeBindings |= BAFlags::ListCellRange;
1713 // is control bound to XForms?
1714 if( !getXFormsBindName( m_xProps ).isEmpty() )
1716 m_nIncludeBindings |= BAFlags::XFormsBind;
1719 // is (list-)control bound to XForms list?
1720 if( !getXFormsListBindName( m_xProps ).isEmpty() )
1722 m_nIncludeBindings |= BAFlags::XFormsListBind;
1725 // does the control have an XForms submission?
1726 if( !getXFormsSubmissionName( m_xProps ).isEmpty() )
1728 m_nIncludeBindings |= BAFlags::XFormsSubmission;
1732 void OControlExport::exportCellBindingAttributes( bool _bIncludeListLinkageType )
1736 FormCellBindingHelper aHelper( m_xProps, nullptr );
1737 Reference< XValueBinding > xBinding( aHelper.getCurrentBinding() );
1738 OSL_ENSURE( xBinding.is(), "OControlExport::exportCellBindingAttributes: invalid bindable or invalid binding!" );
1739 if ( xBinding.is() )
1741 AddAttribute(
1742 OAttributeMetaData::getBindingAttributeNamespace(),
1743 OAttributeMetaData::getBindingAttributeName( BAFlags::LinkedCell ),
1744 aHelper.getStringAddressFromCellBinding( xBinding )
1747 if ( _bIncludeListLinkageType )
1749 sal_Int16 nLinkageType = FormCellBindingHelper::isCellIntegerBinding( xBinding ) ? 1 : 0;
1751 OUStringBuffer sBuffer;
1752 SvXMLUnitConverter::convertEnum(
1753 sBuffer,
1754 nLinkageType,
1755 aListLinkageMap
1758 AddAttribute(
1759 OAttributeMetaData::getBindingAttributeNamespace(),
1760 OAttributeMetaData::getBindingAttributeName( BAFlags::ListLinkingType ),
1761 sBuffer.makeStringAndClear()
1767 catch( const Exception& )
1769 TOOLS_WARN_EXCEPTION( "xmloff.forms", "OControlExport::exportCellBindingAttributes" );
1773 void OControlExport::exportXFormsBindAttributes()
1775 OUString sBindName = getXFormsBindName( m_xProps );
1776 AddAttribute( XML_NAMESPACE_XFORMS, XML_BIND, sBindName );
1778 void OControlExport::exportXFormsListAttributes()
1780 OUString sBindName = getXFormsListBindName( m_xProps );
1781 AddAttribute( XML_NAMESPACE_FORM, XML_XFORMS_LIST_SOURCE, sBindName );
1783 void OControlExport::exportXFormsSubmissionAttributes()
1785 OUString sSubmission = getXFormsSubmissionName( m_xProps );
1786 AddAttribute( XML_NAMESPACE_FORM, XML_XFORMS_SUBMISSION, sSubmission );
1788 void OControlExport::exportCellListSourceRange( )
1792 Reference< XListEntrySink > xSink( m_xProps, UNO_QUERY );
1793 Reference< XListEntrySource > xSource;
1794 if ( xSink.is() )
1795 xSource = xSink->getListEntrySource();
1796 OSL_ENSURE( xSource.is(), "OControlExport::exportCellListSourceRange: list source or sink!" );
1797 if ( xSource.is() )
1799 FormCellBindingHelper aHelper( m_xProps, nullptr );
1801 AddAttribute(
1802 OAttributeMetaData::getBindingAttributeNamespace(),
1803 OAttributeMetaData::getBindingAttributeName( BAFlags::ListCellRange ),
1804 aHelper.getStringAddressFromCellListSource( xSource )
1808 catch( const Exception& )
1810 TOOLS_WARN_EXCEPTION( "xmloff.forms", "OControlExport::exportCellListSourceRange" );
1814 void OControlExport::exportImagePositionAttributes()
1818 sal_Int16 nImagePosition = ImagePosition::Centered;
1819 OSL_VERIFY( m_xProps->getPropertyValue( PROPERTY_IMAGE_POSITION ) >>= nImagePosition );
1820 OSL_ENSURE( ( nImagePosition >= ImagePosition::LeftTop ) && ( nImagePosition <= ImagePosition::Centered ),
1821 "OControlExport::exportImagePositionAttributes: don't know this image position!" );
1823 if ( ( nImagePosition < ImagePosition::LeftTop ) || ( nImagePosition > ImagePosition::Centered ) )
1824 // this is important to prevent potential buffer overflows below, so don't optimize
1825 nImagePosition = ImagePosition::Centered;
1827 if ( nImagePosition == ImagePosition::Centered )
1829 AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_POSITION ), GetXMLToken( XML_CENTER ) );
1831 else
1833 const XMLTokenEnum eXmlImagePositions[] =
1835 XML_START, XML_END, XML_TOP, XML_BOTTOM
1837 const XMLTokenEnum eXmlImageAligns[] =
1839 XML_START, XML_CENTER, XML_END
1842 XMLTokenEnum eXmlImagePosition = eXmlImagePositions[ nImagePosition / 3 ];
1843 XMLTokenEnum eXmlImageAlign = eXmlImageAligns [ nImagePosition % 3 ];
1845 AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_POSITION ), GetXMLToken( eXmlImagePosition ) );
1846 AddAttribute( XML_NAMESPACE_FORM, GetXMLToken( XML_IMAGE_ALIGN ), GetXMLToken( eXmlImageAlign ) );
1849 exportedProperty( PROPERTY_IMAGE_POSITION );
1850 // some of the controls which have an ImagePosition also have an ImageAlign for compatibility
1851 // reasons. Since the ImageAlign values simply represent a sub set of the ImagePosition values,
1852 // we don't need to export ImageAlign anymore
1853 exportedProperty( PROPERTY_IMAGE_ALIGN );
1855 catch( const Exception& )
1857 DBG_UNHANDLED_EXCEPTION("xmloff.forms");
1861 bool OControlExport::controlHasActiveDataBinding() const
1865 // currently exchanging the data with a database column?
1866 OUString sBoundFieldPropertyName( "BoundField" );
1867 if ( m_xPropertyInfo.is() && m_xPropertyInfo->hasPropertyByName( sBoundFieldPropertyName ) )
1869 Reference< XPropertySet > xBoundField;
1870 m_xProps->getPropertyValue( sBoundFieldPropertyName ) >>= xBoundField;
1871 if ( xBoundField.is() )
1872 return true;
1875 // currently exchanging data with an external binding?
1876 Reference< XBindableValue > xBindable( m_xProps, UNO_QUERY );
1877 if ( xBindable.is() && xBindable->getValueBinding().is() )
1878 return true;
1880 catch( const Exception& )
1882 TOOLS_WARN_EXCEPTION( "xmloff.forms", "OColumnExport::controlHasActiveDataBinding" );
1885 return false;
1888 bool OControlExport::controlHasUserSuppliedListEntries() const
1892 // an external list source?
1893 Reference< XListEntrySink > xEntrySink( m_xProps, UNO_QUERY );
1894 if ( xEntrySink.is() && xEntrySink->getListEntrySource().is() )
1895 return false;
1897 if ( m_xPropertyInfo.is() && m_xPropertyInfo->hasPropertyByName( PROPERTY_LISTSOURCETYPE ) )
1899 ListSourceType eListSourceType = ListSourceType_VALUELIST;
1900 OSL_VERIFY( m_xProps->getPropertyValue( PROPERTY_LISTSOURCETYPE ) >>= eListSourceType );
1901 if ( eListSourceType == ListSourceType_VALUELIST )
1902 // for value lists, the list entries as entered by the user are used
1903 return true;
1905 // for every other type, the list entries are filled with some data obtained
1906 // from a database - if and only if the ListSource property is not empty
1907 return getScalarListSourceValue().isEmpty();
1910 catch( const Exception& )
1912 DBG_UNHANDLED_EXCEPTION("xmloff.forms");
1915 OSL_FAIL( "OControlExport::controlHasUserSuppliedListEntries: unreachable code!" );
1916 // this method should be called for list and combo boxes only
1917 return true;
1920 //= OColumnExport
1921 OColumnExport::OColumnExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxControl, const OUString& _rControlId,
1922 const Sequence< ScriptEventDescriptor >& _rEvents)
1923 :OControlExport(_rContext, _rxControl, _rControlId, OUString(), _rEvents)
1927 OColumnExport::~OColumnExport()
1931 void OColumnExport::exportServiceNameAttribute()
1933 // the attribute "service name" (which has a slightly different meaning for columns
1934 DBG_CHECK_PROPERTY( PROPERTY_COLUMNSERVICENAME, OUString );
1935 OUString sColumnServiceName;
1936 m_xProps->getPropertyValue(PROPERTY_COLUMNSERVICENAME) >>= sColumnServiceName;
1937 // the service name is a full qualified one (i.e. com.sun.star.form.TextField), but the
1938 // real service name for the column (for use with the XGridColumnFactory) is only the last
1939 // token of this complete name.
1940 sal_Int32 nLastSep = sColumnServiceName.lastIndexOf('.');
1941 OSL_ENSURE(-1 != nLastSep, "OColumnExport::startExportElement: invalid service name!");
1942 sColumnServiceName = sColumnServiceName.copy(nLastSep + 1);
1943 sColumnServiceName =
1944 m_rContext.getGlobalContext().GetNamespaceMap().GetQNameByKey(
1945 XML_NAMESPACE_OOO, sColumnServiceName );
1946 // add the attribute
1947 AddAttribute( OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::ServiceName)
1948 , OAttributeMetaData::getCommonControlAttributeName(CCAFlags::ServiceName)
1949 , sColumnServiceName);
1950 // flag the property as "handled"
1951 exportedProperty(PROPERTY_COLUMNSERVICENAME);
1955 const char* OColumnExport::getOuterXMLElementName() const
1957 return "column";
1960 void OColumnExport::exportAttributes()
1962 OControlExport::exportAttributes();
1964 // the attribute "label"
1965 exportStringPropertyAttribute(
1966 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::Label),
1967 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Label),
1968 PROPERTY_LABEL);
1970 // the style attribute
1971 OUString sStyleName = m_rContext.getObjectStyleName( m_xProps );
1972 if ( !sStyleName.isEmpty() )
1974 AddAttribute(
1975 OAttributeMetaData::getSpecialAttributeNamespace( SCAFlags::ColumnStyleName ),
1976 OAttributeMetaData::getSpecialAttributeName( SCAFlags::ColumnStyleName ),
1977 sStyleName
1982 void OColumnExport::examine()
1984 OControlExport::examine();
1986 // grid columns miss some properties of the controls they're representing
1987 m_nIncludeCommon &= ~CCAFlags(CCAFlags::For | CCAFlags::Printable | CCAFlags::TabIndex | CCAFlags::TabStop | CCAFlags::Label);
1988 m_nIncludeSpecial &= ~SCAFlags(SCAFlags::EchoChar | SCAFlags::AutoCompletion | SCAFlags::Multiple | SCAFlags::MultiLine);
1990 if (FormComponentType::DATEFIELD != m_nClassId)
1991 // except date fields, no column has the DropDown property
1992 m_nIncludeCommon &= ~CCAFlags::Dropdown;
1995 //= OFormExport
1996 OFormExport::OFormExport(IFormsExportContext& _rContext, const Reference< XPropertySet >& _rxForm,
1997 const Sequence< ScriptEventDescriptor >& _rEvents)
1998 :OElementExport(_rContext, _rxForm, _rEvents)
1999 ,m_bCreateConnectionResourceElement(false)
2001 OSL_ENSURE(m_xProps.is(), "OFormExport::OFormExport: invalid arguments!");
2004 const char* OFormExport::getXMLElementName() const
2006 return "form";
2009 void OFormExport::exportSubTags()
2011 if ( m_bCreateConnectionResourceElement && m_xProps.is() )
2013 m_rContext.getGlobalContext().ClearAttrList();
2014 OUString sPropValue;
2015 m_xProps->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sPropValue; // if set it is a file url
2016 if ( sPropValue.isEmpty() )
2017 m_xProps->getPropertyValue( PROPERTY_URL ) >>= sPropValue;
2018 if ( !sPropValue.isEmpty() )
2019 AddAttribute(
2020 OAttributeMetaData::getCommonControlAttributeNamespace(CCAFlags::TargetLocation),
2021 OAttributeMetaData::getCommonControlAttributeName(CCAFlags::TargetLocation),
2022 m_rContext.getGlobalContext().GetRelativeReference(sPropValue));
2023 if ( m_rContext.getGlobalContext().GetAttrList().getLength() )
2025 SvXMLElementExport aFormElement(m_rContext.getGlobalContext(), XML_NAMESPACE_FORM, xmloff::token::XML_CONNECTION_RESOURCE, true, true);
2029 // let the base class export the remaining properties and the events
2030 OElementExport::exportSubTags();
2031 // loop through all children
2032 Reference< XIndexAccess > xCollection(m_xProps, UNO_QUERY);
2033 OSL_ENSURE(xCollection.is(), "OFormLayerXMLExport::implExportForm: a form which is not an index access? Suspicious!");
2035 if (xCollection.is())
2036 m_rContext.exportCollectionElements(xCollection);
2039 void OFormExport::exportAttributes()
2041 sal_Int32 i=0;
2043 // the string properties
2045 static const FormAttributes eStringPropertyIds[] =
2047 faName, /*faAction,*/ faCommand, faFilter, faOrder
2049 static const rtl::OUStringConstExpr aStringPropertyNames[] =
2051 PROPERTY_NAME, /*PROPERTY_TARGETURL,*/ PROPERTY_COMMAND, PROPERTY_FILTER, PROPERTY_ORDER
2053 static const sal_Int32 nIdCount = std::size(eStringPropertyIds);
2054 #if OSL_DEBUG_LEVEL > 0
2055 static const sal_Int32 nNameCount = std::size(aStringPropertyNames);
2056 OSL_ENSURE((nIdCount == nNameCount),
2057 "OFormExport::exportAttributes: somebody tampered with the maps (1)!");
2058 #endif
2059 for (i=0; i<nIdCount; ++i)
2060 exportStringPropertyAttribute(
2061 OAttributeMetaData::getFormAttributeNamespace(eStringPropertyIds[i]),
2062 OAttributeMetaData::getFormAttributeName(eStringPropertyIds[i]),
2063 aStringPropertyNames[i]);
2065 // #i112082# xlink:type is added as part of exportTargetLocationAttribute
2067 // now export the data source name or databaselocation or connection resource
2068 OUString sPropValue;
2069 m_xProps->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sPropValue;
2070 m_bCreateConnectionResourceElement = sPropValue.isEmpty();
2071 if ( !m_bCreateConnectionResourceElement )
2073 INetURLObject aURL(sPropValue);
2074 m_bCreateConnectionResourceElement = ( aURL.GetProtocol() == INetProtocol::File );
2075 if ( !m_bCreateConnectionResourceElement )
2076 exportStringPropertyAttribute(
2077 OAttributeMetaData::getFormAttributeNamespace(faDatasource),
2078 OAttributeMetaData::getFormAttributeName(faDatasource),
2079 PROPERTY_DATASOURCENAME);
2081 else
2082 exportedProperty(PROPERTY_URL);
2083 if ( m_bCreateConnectionResourceElement )
2084 exportedProperty(PROPERTY_DATASOURCENAME);
2087 // the boolean properties
2089 static const FormAttributes eBooleanPropertyIds[] =
2091 faAllowDeletes, faAllowInserts, faAllowUpdates, faApplyFilter, faEscapeProcessing, faIgnoreResult
2093 static const rtl::OUStringConstExpr pBooleanPropertyNames[] =
2095 PROPERTY_ALLOWDELETES,
2096 PROPERTY_ALLOWINSERTS,
2097 PROPERTY_ALLOWUPDATES,
2098 PROPERTY_APPLYFILTER,
2099 PROPERTY_ESCAPEPROCESSING,
2100 PROPERTY_IGNORERESULT
2102 static const BoolAttrFlags nBooleanPropertyAttrFlags[] =
2104 BoolAttrFlags::DefaultTrue, BoolAttrFlags::DefaultTrue, BoolAttrFlags::DefaultTrue, BoolAttrFlags::DefaultFalse, BoolAttrFlags::DefaultTrue, BoolAttrFlags::DefaultFalse
2106 static const sal_Int32 nIdCount = std::size(eBooleanPropertyIds);
2107 #if OSL_DEBUG_LEVEL > 0
2108 static const sal_Int32 nNameCount = std::size(pBooleanPropertyNames);
2109 static const sal_Int32 nFlagsCount = std::size(nBooleanPropertyAttrFlags);
2110 OSL_ENSURE((nIdCount == nNameCount) && (nNameCount == nFlagsCount),
2111 "OFormExport::exportAttributes: somebody tampered with the maps (2)!");
2112 #endif
2113 for (i=0; i<nIdCount; ++i)
2114 exportBooleanPropertyAttribute(
2115 OAttributeMetaData::getFormAttributeNamespace(eBooleanPropertyIds[i]),
2116 OAttributeMetaData::getFormAttributeName(eBooleanPropertyIds[i]),
2117 pBooleanPropertyNames[i],
2118 nBooleanPropertyAttrFlags[i]
2122 // the enum properties
2124 exportEnumPropertyAttribute(
2125 OAttributeMetaData::getFormAttributeNamespace(faEnctype),
2126 OAttributeMetaData::getFormAttributeName(faEnctype),
2127 PROPERTY_SUBMIT_ENCODING,
2128 aSubmitEncodingMap,
2129 FormSubmitEncoding_URL,
2130 false
2132 exportEnumPropertyAttribute(
2133 OAttributeMetaData::getFormAttributeNamespace(faMethod),
2134 OAttributeMetaData::getFormAttributeName(faMethod),
2135 PROPERTY_SUBMIT_METHOD,
2136 aSubmitMethodMap,
2137 FormSubmitMethod_GET,
2138 false
2140 exportEnumPropertyAttribute(
2141 OAttributeMetaData::getFormAttributeNamespace(faCommandType),
2142 OAttributeMetaData::getFormAttributeName(faCommandType),
2143 PROPERTY_COMMAND_TYPE,
2144 aCommandTypeMap,
2145 CommandType::COMMAND,
2146 false
2148 exportEnumPropertyAttribute(
2149 OAttributeMetaData::getFormAttributeNamespace(faNavigationMode),
2150 OAttributeMetaData::getFormAttributeName(faNavigationMode),
2151 PROPERTY_NAVIGATION,
2152 aNavigationTypeMap,
2153 NavigationBarMode_CURRENT,
2154 false
2156 exportEnumPropertyAttribute(
2157 OAttributeMetaData::getFormAttributeNamespace(faTabbingCycle),
2158 OAttributeMetaData::getFormAttributeName(faTabbingCycle),
2159 PROPERTY_CYCLE,
2160 aTabulatorCycleMap,
2161 TabulatorCycle_RECORDS,
2162 true
2166 // the service name
2167 exportServiceNameAttribute();
2168 // the target frame
2169 exportTargetFrameAttribute();
2170 // the target URL
2171 exportTargetLocationAttribute(true); // #i110911# add type attribute (for form, but not for control)
2173 // master fields
2174 exportStringSequenceAttribute(
2175 OAttributeMetaData::getFormAttributeNamespace(faMasterFields),
2176 OAttributeMetaData::getFormAttributeName(faMasterFields),
2177 PROPERTY_MASTERFIELDS);
2178 // detail fields
2179 exportStringSequenceAttribute(
2180 OAttributeMetaData::getFormAttributeNamespace(faDetailFields),
2181 OAttributeMetaData::getFormAttributeName(faDetailFields),
2182 PROPERTY_DETAILFIELDS);
2184 } // namespace xmloff
2186 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */