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