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 #include "formcellbinding.hxx" 27 #include <com/sun/star/form/binding/XBindableValue.hpp> 28 #include <com/sun/star/form/binding/XListEntrySink.hpp> 29 #include <com/sun/star/form/XGridColumnFactory.hpp> 30 #include <com/sun/star/frame/XModel.hpp> 31 #include <com/sun/star/container/XChild.hpp> 32 #include <com/sun/star/container/XNamed.hpp> 33 #include <com/sun/star/drawing/XDrawPageSupplier.hpp> 34 #include <com/sun/star/table/XCellRange.hpp> 35 #include <com/sun/star/form/XFormsSupplier.hpp> 36 #include <com/sun/star/form/XForm.hpp> 37 #include <com/sun/star/lang/XServiceInfo.hpp> 38 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 39 #include <com/sun/star/beans/NamedValue.hpp> 40 #include "strings.hxx" 41 #include <osl/diagnose.h> 42 #include <rtl/logfile.hxx> 43 44 #include <functional> 45 #include <algorithm> 46 47 //............................................................................ 48 namespace xmloff 49 { 50 //............................................................................ 51 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::beans; 54 using namespace ::com::sun::star::frame; 55 using namespace ::com::sun::star::sheet; 56 using namespace ::com::sun::star::container; 57 using namespace ::com::sun::star::drawing; 58 using namespace ::com::sun::star::table; 59 using namespace ::com::sun::star::form; 60 using namespace ::com::sun::star::lang; 61 using namespace ::com::sun::star::form::binding; 62 63 namespace 64 { 65 using ::com::sun::star::uno::Reference; 66 using ::com::sun::star::uno::XInterface; 67 using ::com::sun::star::container::XChild; 68 using ::com::sun::star::frame::XModel; 69 using ::com::sun::star::uno::UNO_QUERY; 70 71 //.................................................................... 72 template< class TYPE > 73 Reference< TYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode ) 74 { 75 Reference< TYPE > xTypedNode( _rxModelNode, UNO_QUERY ); 76 if ( xTypedNode.is() ) 77 return xTypedNode; 78 else 79 { 80 Reference< XChild > xChild( _rxModelNode, UNO_QUERY ); 81 if ( xChild.is() ) 82 return getTypedModelNode< TYPE >( xChild->getParent() ); 83 else 84 return NULL; 85 } 86 } 87 88 //.................................................................... 89 Reference< XModel > getDocument( const Reference< XInterface >& _rxModelNode ) 90 { 91 return getTypedModelNode< XModel >( _rxModelNode ); 92 } 93 94 //.................................................................... 95 struct StringCompare : public ::std::unary_function< ::rtl::OUString, bool > 96 { 97 private: 98 const ::rtl::OUString m_sReference; 99 100 public: 101 StringCompare( const ::rtl::OUString& _rReference ) : m_sReference( _rReference ) { } 102 103 inline bool operator()( const ::rtl::OUString& _rCompare ) 104 { 105 return ( _rCompare == m_sReference ); 106 } 107 }; 108 } 109 110 //======================================================================== 111 //= FormCellBindingHelper 112 //======================================================================== 113 //------------------------------------------------------------------------ 114 FormCellBindingHelper::FormCellBindingHelper( const Reference< XPropertySet >& _rxControlModel, const Reference< XModel >& _rxDocument ) 115 :m_xControlModel( _rxControlModel ) 116 ,m_xDocument( _rxDocument, UNO_QUERY ) 117 { 118 OSL_ENSURE( m_xControlModel.is(), "FormCellBindingHelper::FormCellBindingHelper: invalid control model!" ); 119 120 if ( !m_xDocument.is() ) 121 m_xDocument = m_xDocument.query( getDocument( m_xControlModel ) ); 122 OSL_ENSURE( m_xDocument.is(), "FormCellBindingHelper::FormCellBindingHelper: Did not find the spreadsheet document!" ); 123 } 124 125 //------------------------------------------------------------------------ 126 sal_Bool FormCellBindingHelper::livesInSpreadsheetDocument( const Reference< XPropertySet >& _rxControlModel ) 127 { 128 Reference< XSpreadsheetDocument > xDocument( getDocument( _rxControlModel ), UNO_QUERY ); 129 return xDocument.is(); 130 } 131 132 //------------------------------------------------------------------------ 133 bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription, CellAddress& /* [out] */ _rAddress, sal_Int16 /*_nAssumeSheet*/ ) const 134 { 135 Any aAddress; 136 return doConvertAddressRepresentations( 137 PROPERTY_FILE_REPRESENTATION, 138 makeAny( _rAddressDescription ), 139 PROPERTY_ADDRESS, 140 aAddress, 141 false 142 ) 143 && ( aAddress >>= _rAddress ); 144 } 145 146 //------------------------------------------------------------------------ 147 bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription, 148 CellRangeAddress& /* [out] */ _rAddress ) const 149 { 150 Any aAddress; 151 return doConvertAddressRepresentations( 152 PROPERTY_FILE_REPRESENTATION, 153 makeAny( _rAddressDescription ), 154 PROPERTY_ADDRESS, 155 aAddress, 156 true 157 ) 158 && ( aAddress >>= _rAddress ); 159 } 160 161 //------------------------------------------------------------------------ 162 Reference< XValueBinding > FormCellBindingHelper::createCellBindingFromStringAddress( const ::rtl::OUString& _rAddress, bool _bUseIntegerBinding ) const 163 { 164 Reference< XValueBinding > xBinding; 165 if ( !m_xDocument.is() ) 166 // very bad ... 167 return xBinding; 168 169 // get the UNO representation of the address 170 CellAddress aAddress; 171 if ( !_rAddress.getLength() || !convertStringAddress( _rAddress, aAddress ) ) 172 return xBinding; 173 174 xBinding = xBinding.query( createDocumentDependentInstance( 175 _bUseIntegerBinding ? SERVICE_LISTINDEXCELLBINDING : SERVICE_CELLVALUEBINDING, 176 PROPERTY_BOUND_CELL, 177 makeAny( aAddress ) 178 ) ); 179 180 return xBinding; 181 } 182 183 //------------------------------------------------------------------------ 184 Reference< XListEntrySource > FormCellBindingHelper::createCellListSourceFromStringAddress( const ::rtl::OUString& _rAddress ) const 185 { 186 Reference< XListEntrySource > xSource; 187 188 CellRangeAddress aRangeAddress; 189 if ( !convertStringAddress( _rAddress, aRangeAddress ) ) 190 return xSource; 191 192 // create a range object for this address 193 xSource = xSource.query( createDocumentDependentInstance( 194 SERVICE_CELLRANGELISTSOURCE, 195 PROPERTY_LIST_CELL_RANGE, 196 makeAny( aRangeAddress ) 197 ) ); 198 199 return xSource; 200 } 201 202 //------------------------------------------------------------------------ 203 ::rtl::OUString FormCellBindingHelper::getStringAddressFromCellBinding( const Reference< XValueBinding >& _rxBinding ) const 204 { 205 OSL_PRECOND( !_rxBinding.is() || isCellBinding( _rxBinding ), "FormCellBindingHelper::getStringAddressFromCellBinding: this is no cell binding!" ); 206 207 ::rtl::OUString sAddress; 208 try 209 { 210 Reference< XPropertySet > xBindingProps( _rxBinding, UNO_QUERY ); 211 OSL_ENSURE( xBindingProps.is() || !_rxBinding.is(), "FormCellBindingHelper::getStringAddressFromCellBinding: no property set for the binding!" ); 212 if ( xBindingProps.is() ) 213 { 214 CellAddress aAddress; 215 xBindingProps->getPropertyValue( PROPERTY_BOUND_CELL ) >>= aAddress; 216 217 Any aStringAddress; 218 doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aAddress ), 219 PROPERTY_FILE_REPRESENTATION, aStringAddress, false ); 220 221 aStringAddress >>= sAddress; 222 } 223 } 224 catch( const Exception& ) 225 { 226 OSL_ENSURE( sal_False, "FormCellBindingHelper::getStringAddressFromCellBinding: caught an exception!" ); 227 } 228 229 return sAddress; 230 } 231 232 //------------------------------------------------------------------------ 233 ::rtl::OUString FormCellBindingHelper::getStringAddressFromCellListSource( const Reference< XListEntrySource >& _rxSource ) const 234 { 235 OSL_PRECOND( !_rxSource.is() || isCellRangeListSource( _rxSource ), "FormCellBindingHelper::getStringAddressFromCellListSource: this is no cell list source!" ); 236 237 ::rtl::OUString sAddress; 238 try 239 { 240 Reference< XPropertySet > xSourceProps( _rxSource, UNO_QUERY ); 241 OSL_ENSURE( xSourceProps.is() || !_rxSource.is(), "FormCellBindingHelper::getStringAddressFromCellListSource: no property set for the list source!" ); 242 if ( xSourceProps.is() ) 243 { 244 CellRangeAddress aRangeAddress; 245 xSourceProps->getPropertyValue( PROPERTY_LIST_CELL_RANGE ) >>= aRangeAddress; 246 247 Any aStringAddress; 248 doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aRangeAddress ), 249 PROPERTY_FILE_REPRESENTATION, aStringAddress, true ); 250 aStringAddress >>= sAddress; 251 } 252 } 253 catch( const Exception& ) 254 { 255 OSL_ENSURE( sal_False, "FormCellBindingHelper::getStringAddressFromCellListSource: caught an exception!" ); 256 } 257 258 return sAddress; 259 } 260 261 //------------------------------------------------------------------------ 262 bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const Reference< XSpreadsheetDocument >& _rxDocument, const ::rtl::OUString& _rService ) SAL_THROW(()) 263 { 264 bool bYesItIs = false; 265 266 try 267 { 268 Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY ); 269 if ( xSI.is() && xSI->supportsService( SERVICE_SPREADSHEET_DOCUMENT ) ) 270 { 271 Reference< XMultiServiceFactory > xDocumentFactory( _rxDocument, UNO_QUERY ); 272 OSL_ENSURE( xDocumentFactory.is(), "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: spreadsheet document, but no factory?" ); 273 274 Sequence< ::rtl::OUString > aAvailableServices; 275 if ( xDocumentFactory.is() ) 276 aAvailableServices = xDocumentFactory->getAvailableServiceNames( ); 277 278 const ::rtl::OUString* pFound = ::std::find_if( 279 aAvailableServices.getConstArray(), 280 aAvailableServices.getConstArray() + aAvailableServices.getLength(), 281 StringCompare( _rService ) 282 ); 283 if ( pFound - aAvailableServices.getConstArray() < aAvailableServices.getLength() ) 284 { 285 bYesItIs = true; 286 } 287 } 288 } 289 catch( const Exception& ) 290 { 291 OSL_ENSURE( sal_False, "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: caught an exception!" ); 292 } 293 294 return bYesItIs; 295 } 296 297 //------------------------------------------------------------------------ 298 bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const ::rtl::OUString& _rService ) const SAL_THROW(()) 299 { 300 return isSpreadsheetDocumentWhichSupplies( m_xDocument, _rService ); 301 } 302 303 //------------------------------------------------------------------------ 304 bool FormCellBindingHelper::isListCellRangeAllowed( const Reference< XModel >& _rxDocument ) 305 { 306 return isSpreadsheetDocumentWhichSupplies( 307 Reference< XSpreadsheetDocument >( _rxDocument, UNO_QUERY ), 308 SERVICE_CELLRANGELISTSOURCE 309 ); 310 } 311 312 //------------------------------------------------------------------------ 313 bool FormCellBindingHelper::isListCellRangeAllowed( ) const 314 { 315 bool bAllow( false ); 316 317 Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); 318 if ( xSink.is() ) 319 { 320 bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_CELLRANGELISTSOURCE ); 321 } 322 323 return bAllow; 324 } 325 326 //------------------------------------------------------------------------ 327 bool FormCellBindingHelper::isCellBindingAllowed( ) const 328 { 329 bool bAllow( false ); 330 331 Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); 332 if ( xBindable.is() ) 333 { 334 // the control can potentially be bound to an external value 335 // Does it live within a Calc document, and is able to supply CellBindings? 336 bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_CELLVALUEBINDING ); 337 } 338 339 return bAllow; 340 } 341 342 //------------------------------------------------------------------------ 343 bool FormCellBindingHelper::isCellBindingAllowed( const Reference< XModel >& _rxDocument ) 344 { 345 return isSpreadsheetDocumentWhichSupplies( 346 Reference< XSpreadsheetDocument >( _rxDocument, UNO_QUERY ), 347 SERVICE_CELLVALUEBINDING 348 ); 349 } 350 351 //------------------------------------------------------------------------ 352 bool FormCellBindingHelper::isCellBinding( const Reference< XValueBinding >& _rxBinding ) const 353 { 354 return doesComponentSupport( _rxBinding.get(), SERVICE_CELLVALUEBINDING ); 355 } 356 357 //------------------------------------------------------------------------ 358 bool FormCellBindingHelper::isCellIntegerBinding( const Reference< XValueBinding >& _rxBinding ) const 359 { 360 return doesComponentSupport( _rxBinding.get(), SERVICE_LISTINDEXCELLBINDING ); 361 } 362 363 //------------------------------------------------------------------------ 364 bool FormCellBindingHelper::isCellRangeListSource( const Reference< XListEntrySource >& _rxSource ) const 365 { 366 return doesComponentSupport( _rxSource.get(), SERVICE_CELLRANGELISTSOURCE ); 367 } 368 369 //------------------------------------------------------------------------ 370 bool FormCellBindingHelper::doesComponentSupport( const Reference< XInterface >& _rxComponent, const ::rtl::OUString& _rService ) const 371 { 372 bool bDoes = false; 373 Reference< XServiceInfo > xSI( _rxComponent, UNO_QUERY ); 374 bDoes = xSI.is() && xSI->supportsService( _rService ); 375 return bDoes; 376 } 377 378 //------------------------------------------------------------------------ 379 Reference< XValueBinding > FormCellBindingHelper::getCurrentBinding( ) const 380 { 381 Reference< XValueBinding > xBinding; 382 Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); 383 if ( xBindable.is() ) 384 xBinding = xBindable->getValueBinding(); 385 return xBinding; 386 } 387 388 //------------------------------------------------------------------------ 389 Reference< XListEntrySource > FormCellBindingHelper::getCurrentListSource( ) const 390 { 391 Reference< XListEntrySource > xSource; 392 Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); 393 if ( xSink.is() ) 394 xSource = xSink->getListEntrySource(); 395 return xSource; 396 } 397 398 //------------------------------------------------------------------------ 399 void FormCellBindingHelper::setBinding( const Reference< XValueBinding >& _rxBinding ) 400 { 401 Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY ); 402 OSL_PRECOND( xBindable.is(), "FormCellBindingHelper::setBinding: the object is not bindable!" ); 403 if ( xBindable.is() ) 404 xBindable->setValueBinding( _rxBinding ); 405 } 406 407 //------------------------------------------------------------------------ 408 void FormCellBindingHelper::setListSource( const Reference< XListEntrySource >& _rxSource ) 409 { 410 Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY ); 411 OSL_PRECOND( xSink.is(), "FormCellBindingHelper::setListSource: the object is no list entry sink!" ); 412 if ( xSink.is() ) 413 xSink->setListEntrySource( _rxSource ); 414 } 415 416 //------------------------------------------------------------------------ 417 Reference< XInterface > FormCellBindingHelper::createDocumentDependentInstance( const ::rtl::OUString& _rService, const ::rtl::OUString& _rArgumentName, 418 const Any& _rArgumentValue ) const 419 { 420 Reference< XInterface > xReturn; 421 422 Reference< XMultiServiceFactory > xDocumentFactory( m_xDocument, UNO_QUERY ); 423 OSL_ENSURE( xDocumentFactory.is(), "FormCellBindingHelper::createDocumentDependentInstance: no document service factory!" ); 424 if ( xDocumentFactory.is() ) 425 { 426 try 427 { 428 if ( _rArgumentName.getLength() ) 429 { 430 NamedValue aArg; 431 aArg.Name = _rArgumentName; 432 aArg.Value = _rArgumentValue; 433 434 Sequence< Any > aArgs( 1 ); 435 aArgs[ 0 ] <<= aArg; 436 437 xReturn = xDocumentFactory->createInstanceWithArguments( _rService, aArgs ); 438 } 439 else 440 { 441 xReturn = xDocumentFactory->createInstance( _rService ); 442 } 443 } 444 catch ( const Exception& ) 445 { 446 OSL_ENSURE( sal_False, "FormCellBindingHelper::createDocumentDependentInstance: could not create the binding at the document!" ); 447 } 448 } 449 return xReturn; 450 } 451 452 //------------------------------------------------------------------------ 453 bool FormCellBindingHelper::doConvertAddressRepresentations( const ::rtl::OUString& _rInputProperty, const Any& _rInputValue, 454 const ::rtl::OUString& _rOutputProperty, Any& _rOutputValue, bool _bIsRange ) const SAL_THROW(()) 455 { 456 bool bSuccess = false; 457 458 Reference< XPropertySet > xConverter( 459 createDocumentDependentInstance( 460 _bIsRange ? SERVICE_RANGEADDRESS_CONVERSION : SERVICE_ADDRESS_CONVERSION, 461 ::rtl::OUString(), 462 Any() 463 ), 464 UNO_QUERY 465 ); 466 OSL_ENSURE( xConverter.is(), "FormCellBindingHelper::doConvertAddressRepresentations: could not get a converter service!" ); 467 if ( xConverter.is() ) 468 { 469 try 470 { 471 xConverter->setPropertyValue( _rInputProperty, _rInputValue ); 472 _rOutputValue = xConverter->getPropertyValue( _rOutputProperty ); 473 bSuccess = true; 474 } 475 catch( const Exception& ) 476 { 477 OSL_ENSURE( sal_False, "FormCellBindingHelper::doConvertAddressRepresentations: caught an exception!" ); 478 } 479 } 480 481 return bSuccess; 482 } 483 484 //............................................................................ 485 } // namespace xmloff 486 //............................................................................ 487