1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 27 #include <stdio.h> 28 #include "layerexport.hxx" 29 #include "strings.hxx" 30 #include <xmloff/xmlexp.hxx> 31 #include <xmloff/nmspmap.hxx> 32 #include "xmloff/xmlnmspe.hxx" 33 #include <xmloff/xmluconv.hxx> 34 #include <xmloff/xmlprmap.hxx> 35 #include <xmloff/prhdlfac.hxx> 36 #include "elementexport.hxx" 37 #include <xmloff/families.hxx> 38 #include <xmloff/contextid.hxx> 39 #include <xmloff/controlpropertyhdl.hxx> 40 #include <tools/diagnose_ex.h> 41 #include "controlpropertymap.hxx" 42 #include <com/sun/star/container/XIndexAccess.hpp> 43 #include <com/sun/star/form/XFormsSupplier2.hpp> 44 #include <com/sun/star/xforms/XFormsSupplier.hpp> 45 #include <com/sun/star/form/FormComponentType.hpp> 46 #include <com/sun/star/lang/XServiceInfo.hpp> 47 #include <com/sun/star/container/XChild.hpp> 48 #include <com/sun/star/script/XEventAttacherManager.hpp> 49 #include "eventexport.hxx" 50 #include <xmloff/XMLEventExport.hxx> 51 #include "formevents.hxx" 52 #include <xmloff/xmlnumfe.hxx> 53 #include "xmloff/xformsexport.hxx" 54 55 /** === begin UNO includes === **/ 56 #include <com/sun/star/text/XText.hpp> 57 /** === end UNO includes === **/ 58 59 #include <numeric> 60 61 //......................................................................... 62 namespace xmloff 63 { 64 //......................................................................... 65 66 using namespace ::com::sun::star::uno; 67 using namespace ::com::sun::star::awt; 68 using namespace ::com::sun::star::lang; 69 using namespace ::com::sun::star::beans; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::drawing; 72 using namespace ::com::sun::star::form; 73 using namespace ::com::sun::star::script; 74 using namespace ::com::sun::star::util; 75 using namespace ::com::sun::star::text; 76 77 typedef ::com::sun::star::xforms::XFormsSupplier XXFormsSupplier; 78 79 //===================================================================== 80 //= OFormLayerXMLExport_Impl 81 //===================================================================== 82 //--------------------------------------------------------------------- getControlNumberStyleNamePrefix()83 const ::rtl::OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix() 84 { 85 static const ::rtl::OUString s_sControlNumberStyleNamePrefix = ::rtl::OUString::createFromAscii("C"); 86 return s_sControlNumberStyleNamePrefix; 87 } 88 89 //--------------------------------------------------------------------- OFormLayerXMLExport_Impl(SvXMLExport & _rContext)90 OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext) 91 :m_rContext(_rContext) 92 ,m_pControlNumberStyles(NULL) 93 { 94 initializePropertyMaps(); 95 96 // add our style family to the export context's style pool 97 m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory(); 98 ::vos::ORef< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory.getBodyPtr() ); 99 m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper.getBodyPtr() ); 100 101 // our style family 102 m_rContext.GetAutoStylePool()->AddFamily( 103 XML_STYLE_FAMILY_CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH), 104 m_xStyleExportMapper.getBodyPtr(), 105 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XML_STYLE_FAMILY_CONTROL_PREFIX) ) 106 ); 107 108 // add our event translation table 109 m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation); 110 111 clear(); 112 } 113 ~OFormLayerXMLExport_Impl()114 OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl() 115 { 116 } 117 118 //--------------------------------------------------------------------- impl_isFormPageContainingForms(const Reference<XDrawPage> & _rxDrawPage,Reference<XIndexAccess> & _rxForms)119 sal_Bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms) 120 { 121 Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY); 122 OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!"); 123 if (!xFormsSupp.is()) 124 return sal_False; 125 126 if ( !xFormsSupp->hasForms() ) 127 // nothing to do at all 128 return sal_False; 129 130 _rxForms = Reference< XIndexAccess >(xFormsSupp->getForms(), UNO_QUERY); 131 Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important! 132 OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!"); 133 if (!xSI.is()) 134 return sal_False; 135 136 if (!xSI->supportsService(SERVICE_FORMSCOLLECTION)) 137 { 138 OSL_ENSURE(sal_False, "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!"); 139 // nothing to do 140 return sal_False; 141 } 142 return sal_True; 143 } 144 145 //--------------------------------------------------------------------- exportGridColumn(const Reference<XPropertySet> & _rxColumn,const Sequence<ScriptEventDescriptor> & _rEvents)146 void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn, 147 const Sequence< ScriptEventDescriptor >& _rEvents) 148 { 149 // do the exporting 150 OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents); 151 aExportImpl.doExport(); 152 } 153 154 //--------------------------------------------------------------------- exportControl(const Reference<XPropertySet> & _rxControl,const Sequence<ScriptEventDescriptor> & _rEvents)155 void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl, 156 const Sequence< ScriptEventDescriptor >& _rEvents) 157 { 158 // the list of the referring controls 159 ::rtl::OUString sReferringControls; 160 MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl); 161 if (aReferring != m_aCurrentPageReferring->second.end()) 162 sReferringControls = aReferring->second; 163 164 // the control id (should already have been created in examineForms) 165 ::rtl::OUString sControlId( getControlId( _rxControl ) ); 166 167 // do the exporting 168 OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents); 169 aExportImpl.doExport(); 170 } 171 172 //--------------------------------------------------------------------- exportForm(const Reference<XPropertySet> & _rxProps,const Sequence<ScriptEventDescriptor> & _rEvents)173 void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps, 174 const Sequence< ScriptEventDescriptor >& _rEvents) 175 { 176 OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!"); 177 OFormExport aAttributeHandler(*this, _rxProps, _rEvents); 178 aAttributeHandler.doExport(); 179 } 180 181 //--------------------------------------------------------------------- getStylePropertyMapper()182 ::vos::ORef< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper() 183 { 184 return m_xStyleExportMapper; 185 } 186 187 //--------------------------------------------------------------------- getGlobalContext()188 SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext() 189 { 190 return m_rContext; 191 } 192 193 //--------------------------------------------------------------------- exportCollectionElements(const Reference<XIndexAccess> & _rxCollection)194 void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection) 195 { 196 // step through all the elements of the collection 197 sal_Int32 nElements = _rxCollection->getCount(); 198 199 Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY); 200 Sequence< ScriptEventDescriptor > aElementEvents; 201 202 Reference< XPropertySetInfo > xPropsInfo; 203 Reference< XIndexAccess > xCurrentContainer; 204 for (sal_Int32 i=0; i<nElements; ++i) 205 { 206 try 207 { 208 // extract the current element 209 Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY ); 210 OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!"); 211 if (!xCurrentProps.is()) 212 continue; 213 214 // check if there is a ClassId property on the current element. If so, we assume it to be a control 215 xPropsInfo = xCurrentProps->getPropertySetInfo(); 216 OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!"); 217 if (!xPropsInfo.is()) 218 // without this, a lot of stuff in the export routines may fail 219 continue; 220 221 // if the element is part of a ignore list, we are not allowed to export it 222 if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) ) 223 continue; 224 225 if (xElementEventManager.is()) 226 aElementEvents = xElementEventManager->getScriptEvents(i); 227 228 if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME)) 229 { 230 exportGridColumn(xCurrentProps, aElementEvents); 231 } 232 else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID)) 233 { 234 exportControl(xCurrentProps, aElementEvents); 235 } 236 else 237 { 238 exportForm(xCurrentProps, aElementEvents); 239 } 240 } 241 catch(Exception&) 242 { 243 OSL_ENSURE(sal_False, "OFormLayerXMLExport_Impl::exportCollectionElements: caught an exception ... skipping the current element!"); 244 continue; 245 } 246 } 247 } 248 249 //--------------------------------------------------------------------- getObjectStyleName(const Reference<XPropertySet> & _rxObject)250 ::rtl::OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject ) 251 { 252 ::rtl::OUString aObjectStyle; 253 254 MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject ); 255 if ( m_aGridColumnStyles.end() != aObjectStylePos ) 256 aObjectStyle = aObjectStylePos->second; 257 return aObjectStyle; 258 } 259 260 //--------------------------------------------------------------------- clear()261 void OFormLayerXMLExport_Impl::clear() 262 { 263 m_aControlIds.clear(); 264 m_aReferringControls.clear(); 265 m_aCurrentPageIds = m_aControlIds.end(); 266 m_aCurrentPageReferring = m_aReferringControls.end(); 267 268 m_aControlNumberFormats.clear(); 269 m_aGridColumnStyles.clear(); 270 271 m_aIgnoreList.clear(); 272 } 273 274 //--------------------------------------------------------------------- exportControlNumberStyles()275 void OFormLayerXMLExport_Impl::exportControlNumberStyles() 276 { 277 if (m_pControlNumberStyles) 278 m_pControlNumberStyles->Export(sal_False); 279 } 280 281 //--------------------------------------------------------------------- exportAutoControlNumberStyles()282 void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles() 283 { 284 if ( m_pControlNumberStyles ) 285 m_pControlNumberStyles->Export( sal_True ); 286 } 287 288 //--------------------------------------------------------------------- exportAutoStyles()289 void OFormLayerXMLExport_Impl::exportAutoStyles() 290 { 291 m_rContext.GetAutoStylePool()->exportXML( 292 XML_STYLE_FAMILY_CONTROL_ID, 293 m_rContext.GetDocHandler(), 294 m_rContext.GetMM100UnitConverter(), 295 m_rContext.GetNamespaceMap() 296 ); 297 } 298 299 //--------------------------------------------------------------------- exportForms(const Reference<XDrawPage> & _rxDrawPage)300 void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage) 301 { 302 // get the forms collection of the page 303 Reference< XIndexAccess > xCollectionIndex; 304 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex)) 305 return; 306 307 #if OSL_DEBUG_LEVEL > 0 308 sal_Bool bPageIsKnown = 309 #endif 310 implMoveIterators(_rxDrawPage, sal_False); 311 OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!"); 312 313 // export forms collection 314 exportCollectionElements(xCollectionIndex); 315 } 316 317 //--------------------------------------------------------------------- exportXForms() const318 void OFormLayerXMLExport_Impl::exportXForms() const 319 { 320 // export XForms models 321 ::exportXForms( m_rContext ); 322 } 323 324 //--------------------------------------------------------------------- pageContainsForms(const Reference<XDrawPage> & _rxDrawPage) const325 bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage ) const 326 { 327 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY ); 328 DBG_ASSERT( xFormsSupp.is(), "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" ); 329 return xFormsSupp.is() && xFormsSupp->hasForms(); 330 } 331 332 //--------------------------------------------------------------------- documentContainsXForms() const333 bool OFormLayerXMLExport_Impl::documentContainsXForms() const 334 { 335 Reference< XXFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY ); 336 Reference< XNameContainer > xForms; 337 if ( xXFormSupp.is() ) 338 xForms = xXFormSupp->getXForms(); 339 return xForms.is() && xForms->hasElements(); 340 } 341 342 //--------------------------------------------------------------------- implMoveIterators(const Reference<XDrawPage> & _rxDrawPage,sal_Bool _bClear)343 sal_Bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, sal_Bool _bClear) 344 { 345 sal_Bool bKnownPage = sal_False; 346 347 // the one for the ids 348 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage); 349 if (m_aControlIds.end() == m_aCurrentPageIds) 350 { 351 m_aControlIds[_rxDrawPage] = MapPropertySet2String(); 352 m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage); 353 } 354 else 355 { 356 bKnownPage = sal_True; 357 if (_bClear && !m_aCurrentPageIds->second.empty() ) 358 m_aCurrentPageIds->second.clear(); 359 } 360 361 // the one for the ids of the referring controls 362 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage); 363 if (m_aReferringControls.end() == m_aCurrentPageReferring) 364 { 365 m_aReferringControls[_rxDrawPage] = MapPropertySet2String(); 366 m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage); 367 } 368 else 369 { 370 bKnownPage = sal_True; 371 if (_bClear && !m_aCurrentPageReferring->second.empty() ) 372 m_aCurrentPageReferring->second.clear(); 373 } 374 return bKnownPage; 375 } 376 377 //--------------------------------------------------------------------- seekPage(const Reference<XDrawPage> & _rxDrawPage)378 sal_Bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage) 379 { 380 sal_Bool bKnownPage = implMoveIterators( _rxDrawPage, sal_False ); 381 if ( bKnownPage ) 382 return sal_True; 383 384 // if the page is not yet known, this does not automatically mean that it has 385 // not been examined. Instead, examineForms returns silently and successfully 386 // if a page is a XFormsPageSupplier2, but does not have a forms collection 387 // (This behaviour of examineForms is a performance optimization, to not force 388 // the page to create a forms container just to see that it's empty.) 389 390 // So, in such a case, seekPage is considered to be successful, too, though the 391 // page was not yet known 392 Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY ); 393 if ( xFormsSupp.is() && !xFormsSupp->hasForms() ) 394 return sal_True; 395 396 // anything else means that the page has not been examined before, or it's no 397 // valid form page. Both cases are Bad (TM). 398 return sal_False; 399 } 400 401 //--------------------------------------------------------------------- getControlId(const Reference<XPropertySet> & _rxControl)402 ::rtl::OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl) 403 { 404 OSL_ENSURE(m_aCurrentPageIds != m_aControlIds.end(), "OFormLayerXMLExport_Impl::getControlId: invalid current page!"); 405 OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl), 406 "OFormLayerXMLExport_Impl::getControlId: can not find the control!"); 407 return m_aCurrentPageIds->second[_rxControl]; 408 } 409 410 //--------------------------------------------------------------------- getImmediateNumberStyle(const Reference<XPropertySet> & _rxObject)411 ::rtl::OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject ) 412 { 413 ::rtl::OUString sNumberStyle; 414 415 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject ); 416 if ( -1 != nOwnFormatKey ) 417 sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey ); 418 419 return sNumberStyle; 420 } 421 422 //--------------------------------------------------------------------- getControlNumberStyle(const Reference<XPropertySet> & _rxControl)423 ::rtl::OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl ) 424 { 425 ::rtl::OUString sNumberStyle; 426 427 ConstMapPropertySet2IntIterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl); 428 if (m_aControlNumberFormats.end() != aControlFormatPos) 429 { 430 OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!"); 431 sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second); 432 } 433 // it's allowed to ask for a control which does not have format information. 434 // (This is for performance reasons) 435 436 return sNumberStyle; 437 } 438 439 //--------------------------------------------------------------------- examineForms(const Reference<XDrawPage> & _rxDrawPage)440 void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage) 441 { 442 // get the forms collection of the page 443 Reference< XIndexAccess > xCollectionIndex; 444 if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex)) 445 return; 446 447 // move the iterator which specify the currently handled page 448 #if OSL_DEBUG_LEVEL > 0 449 sal_Bool bPageIsKnown = 450 #endif 451 implMoveIterators(_rxDrawPage, sal_True); 452 OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!"); 453 454 ::std::stack< Reference< XIndexAccess > > aContainerHistory; 455 ::std::stack< sal_Int32 > aIndexHistory; 456 457 Reference< XIndexAccess > xLoop = xCollectionIndex; 458 sal_Int32 nChildPos = 0; 459 do 460 { 461 if (nChildPos < xLoop->getCount()) 462 { 463 Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY ); 464 OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object"); 465 if (!xCurrent.is()) 466 continue; 467 468 if (!checkExamineControl(xCurrent)) 469 { 470 // step down 471 Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY); 472 OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?"); 473 aContainerHistory.push(xLoop); 474 aIndexHistory.push(nChildPos); 475 476 xLoop = xNextContainer; 477 nChildPos = -1; // will be incremented below 478 } 479 ++nChildPos; 480 } 481 else 482 { 483 // step up 484 while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() ) 485 { 486 xLoop = aContainerHistory.top(); 487 aContainerHistory.pop(); 488 nChildPos = aIndexHistory.top(); 489 aIndexHistory.pop(); 490 491 ++nChildPos; 492 } 493 if (nChildPos >= xLoop->getCount()) 494 // exited the loop above because we have no history anymore (0 == aContainerHistory.size()), 495 // and on the current level there are no more children 496 // -> leave 497 break; 498 } 499 } 500 while (xLoop.is()); 501 } 502 503 //--------------------------------------------------------------------- 504 namespace 505 { 506 struct AccumulateSize : public ::std::binary_function< size_t, MapPropertySet2Map::value_type, size_t > 507 { operator ()xmloff::__anonb6839ddf0111::AccumulateSize508 size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const 509 { 510 return _size + _map.second.size(); 511 } 512 }; 513 lcl_findFreeControlId(const MapPropertySet2Map & _rAllPagesControlIds)514 ::rtl::OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds ) 515 { 516 static const ::rtl::OUString sControlIdBase( RTL_CONSTASCII_USTRINGPARAM( "control" ) ); 517 ::rtl::OUString sControlId = sControlIdBase; 518 519 size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), (size_t)0, AccumulateSize() ); 520 sControlId += ::rtl::OUString::valueOf( (sal_Int32)nKnownControlCount + 1 ); 521 522 #ifdef DBG_UTIL 523 // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries 524 // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if 525 // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail. 526 for ( MapPropertySet2Map::const_iterator outer = _rAllPagesControlIds.begin(); 527 outer != _rAllPagesControlIds.end(); 528 ++outer 529 ) 530 for ( MapPropertySet2String::const_iterator inner = outer->second.begin(); 531 inner != outer->second.end(); 532 ++inner 533 ) 534 { 535 OSL_ENSURE( inner->second != sControlId, 536 "lcl_findFreeControlId: auto-generated control ID is already used!" ); 537 } 538 #endif 539 return sControlId; 540 } 541 } 542 543 //--------------------------------------------------------------------- checkExamineControl(const Reference<XPropertySet> & _rxObject)544 sal_Bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject) 545 { 546 Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo(); 547 OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info"); 548 549 sal_Bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID ); 550 if (bIsControl) 551 { 552 // ---------------------------------- 553 // generate a new control id 554 555 // find a free id 556 ::rtl::OUString sCurrentId = lcl_findFreeControlId( m_aControlIds ); 557 // add it to the map 558 m_aCurrentPageIds->second[_rxObject] = sCurrentId; 559 560 // ---------------------------------- 561 // check if this control has a "LabelControl" property referring another control 562 if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) ) 563 { 564 Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY ); 565 if (xCurrentReference.is()) 566 { 567 ::rtl::OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference]; 568 if (sReferencedBy.getLength()) 569 // it's not the first _rxObject referring to the xCurrentReference 570 // -> separate the id 571 sReferencedBy += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); 572 sReferencedBy += sCurrentId; 573 } 574 } 575 576 // ---------------------------------- 577 // check if the control needs a number format style 578 if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) ) 579 { 580 examineControlNumberFormat(_rxObject); 581 } 582 583 // ---------------------------------- 584 // check if it's a control providing text 585 Reference< XText > xControlText( _rxObject, UNO_QUERY ); 586 if ( xControlText.is() ) 587 { 588 m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText ); 589 } 590 591 // ---------------------------------- 592 // check if it is a grid control - in this case, we need special handling for the columns 593 sal_Int16 nControlType = FormComponentType::CONTROL; 594 _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType; 595 if ( FormComponentType::GRIDCONTROL == nControlType ) 596 { 597 collectGridColumnStylesAndIds( _rxObject ); 598 } 599 } 600 601 return bIsControl; 602 } 603 604 //--------------------------------------------------------------------- collectGridColumnStylesAndIds(const Reference<XPropertySet> & _rxControl)605 void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl ) 606 { 607 // loop through all columns of the grid 608 try 609 { 610 Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY ); 611 OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" ); 612 if ( !xContainer.is() ) 613 return; 614 615 Reference< XPropertySetInfo > xColumnPropertiesMeta; 616 617 sal_Int32 nCount = xContainer->getCount(); 618 for ( sal_Int32 i=0; i<nCount; ++i ) 619 { 620 Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY ); 621 OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" ); 622 if ( !xColumnProperties.is() ) 623 continue; 624 625 // ---------------------------------- 626 // generate a new control id 627 628 // find a free id 629 ::rtl::OUString sCurrentId = lcl_findFreeControlId( m_aControlIds ); 630 // add it to the map 631 m_aCurrentPageIds->second[ xColumnProperties ] = sCurrentId; 632 633 // ---------------------------------- 634 // determine a number style, if needed 635 xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo(); 636 // get the styles of the column 637 ::std::vector< XMLPropertyState > aPropertyStates = m_xStyleExportMapper->Filter( xColumnProperties ); 638 639 // care for the number format, additionally 640 ::rtl::OUString sColumnNumberStyle; 641 if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) ) 642 sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties ); 643 644 if ( sColumnNumberStyle.getLength() ) 645 { // the column indeed has a formatting 646 sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE ); 647 // TODO: move this to the ctor 648 OSL_ENSURE ( -1 != nStyleMapIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!"); 649 650 XMLPropertyState aNumberStyleState( nStyleMapIndex, makeAny( sColumnNumberStyle ) ); 651 aPropertyStates.push_back( aNumberStyleState ); 652 } 653 654 #if OSL_DEBUG_LEVEL > 0 655 ::std::vector< XMLPropertyState >::const_iterator aHaveALook = aPropertyStates.begin(); 656 for ( ; aHaveALook != aPropertyStates.end(); ++aHaveALook ) 657 { 658 (void)aHaveALook; 659 } 660 #endif 661 662 // ---------------------------------- 663 // determine the column style 664 665 if ( !aPropertyStates.empty() ) 666 { // add to the style pool 667 ::rtl::OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XML_STYLE_FAMILY_CONTROL_ID, aPropertyStates ); 668 669 OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ), 670 "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" ); 671 672 m_aGridColumnStyles.insert( MapPropertySet2String::value_type( xColumnProperties, sColumnStyleName ) ); 673 } 674 } 675 } 676 catch( const Exception& ) 677 { 678 DBG_UNHANDLED_EXCEPTION(); 679 } 680 } 681 682 //--------------------------------------------------------------------- implExamineControlNumberFormat(const Reference<XPropertySet> & _rxObject)683 sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject ) 684 { 685 // get the format key relative to our own formats supplier 686 sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject ); 687 688 if ( -1 != nOwnFormatKey ) 689 // tell the exporter that we used this format 690 getControlNumberStyleExport()->SetUsed( nOwnFormatKey ); 691 692 return nOwnFormatKey; 693 } 694 695 //--------------------------------------------------------------------- examineControlNumberFormat(const Reference<XPropertySet> & _rxControl)696 void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl ) 697 { 698 sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl ); 699 700 if ( -1 == nOwnFormatKey ) 701 // nothing to do, the number format of this control is void 702 return; 703 704 // remember the format key for this control (we'll be asked in getControlNumberStyle for this) 705 OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl), 706 "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!"); 707 m_aControlNumberFormats[_rxControl] = nOwnFormatKey; 708 } 709 710 //--------------------------------------------------------------------- ensureTranslateFormat(const Reference<XPropertySet> & _rxFormattedControl)711 sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl) 712 { 713 ensureControlNumberStyleExport(); 714 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!"); 715 // (should have been created in ensureControlNumberStyleExport) 716 717 sal_Int32 nOwnFormatKey = -1; 718 719 // the format key (relative to the control's supplier) 720 sal_Int32 nControlFormatKey = -1; 721 Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY); 722 if (aControlFormatKey >>= nControlFormatKey) 723 { 724 // the control's number format 725 Reference< XNumberFormatsSupplier > xControlFormatsSupplier; 726 _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier; 727 Reference< XNumberFormats > xControlFormats; 728 if (xControlFormatsSupplier.is()) 729 xControlFormats = xControlFormatsSupplier->getNumberFormats(); 730 OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!"); 731 732 // obtain the persistent (does not depend on the formats supplier) representation of the control's format 733 Locale aFormatLocale; 734 ::rtl::OUString sFormatDescription; 735 if (xControlFormats.is()) 736 { 737 Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey); 738 739 xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale; 740 xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription; 741 } 742 743 // check if our own formats collection already knows the format 744 nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, sal_False); 745 if (-1 == nOwnFormatKey) 746 { // no, we don't 747 // -> create a new format 748 nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale); 749 } 750 OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!"); 751 } 752 else 753 OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!"); 754 755 return nOwnFormatKey; 756 } 757 758 //--------------------------------------------------------------------- ensureControlNumberStyleExport()759 void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport() 760 { 761 if (!m_pControlNumberStyles) 762 { 763 // create our number formats supplier (if necessary) 764 Reference< XNumberFormatsSupplier > xFormatsSupplier; 765 766 OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!"); 767 // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together 768 769 try 770 { 771 // create it for en-US (does not really matter, as we will specify a locale for every 772 // concrete language to use) 773 Sequence< Any > aSupplierArgs(1); 774 aSupplierArgs[0] <<= Locale ( ::rtl::OUString::createFromAscii("en"), 775 ::rtl::OUString::createFromAscii("US"), 776 ::rtl::OUString() 777 ); 778 // #110680# 779 //Reference< XInterface > xFormatsSupplierUntyped = 780 // ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( 781 // SERVICE_NUMBERFORMATSSUPPLIER, 782 // aSupplierArgs 783 // ); 784 Reference< XInterface > xFormatsSupplierUntyped = 785 m_rContext.getServiceFactory()->createInstanceWithArguments( 786 SERVICE_NUMBERFORMATSSUPPLIER, 787 aSupplierArgs 788 ); 789 OSL_ENSURE(xFormatsSupplierUntyped.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not instantiate a number formats supplier!"); 790 791 xFormatsSupplier = Reference< XNumberFormatsSupplier >(xFormatsSupplierUntyped, UNO_QUERY); 792 if (xFormatsSupplier.is()) 793 m_xControlNumberFormats = xFormatsSupplier->getNumberFormats(); 794 } 795 catch(const Exception&) 796 { 797 } 798 799 OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!"); 800 801 // create the exporter 802 m_pControlNumberStyles = new SvXMLNumFmtExport(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix()); 803 } 804 } 805 806 //--------------------------------------------------------------------- getControlNumberStyleExport()807 SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport() 808 { 809 ensureControlNumberStyleExport(); 810 return m_pControlNumberStyles; 811 } 812 813 //--------------------------------------------------------------------- excludeFromExport(const Reference<XControlModel> _rxControl)814 void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel > _rxControl ) 815 { 816 Reference< XPropertySet > xProps( _rxControl, UNO_QUERY ); 817 OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" ); 818 #if OSL_DEBUG_LEVEL > 0 819 ::std::pair< PropertySetBag::iterator, bool > aPos = 820 #endif 821 m_aIgnoreList.insert( xProps ); 822 OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" ); 823 } 824 825 //......................................................................... 826 } // namespace xmloff 827 //......................................................................... 828 829 830