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_forms.hxx" 26 27 #include "ListBox.hxx" 28 #include "property.hxx" 29 #include "property.hrc" 30 #include "services.hxx" 31 #include "frm_resource.hxx" 32 #include "frm_resource.hrc" 33 #include "BaseListBox.hxx" 34 #include "listenercontainers.hxx" 35 #include "componenttools.hxx" 36 37 /** === begin UNO includes === **/ 38 #include <com/sun/star/util/XNumberFormatTypes.hpp> 39 #include <com/sun/star/sdbc/XRowSet.hpp> 40 #include <com/sun/star/container/XIndexAccess.hpp> 41 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> 42 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 43 #include <com/sun/star/util/NumberFormat.hpp> 44 #include <com/sun/star/awt/XWindow.hpp> 45 #include <com/sun/star/sdbc/XConnection.hpp> 46 #include <com/sun/star/sdb/CommandType.hpp> 47 /** === end UNO includes === **/ 48 49 #include <comphelper/basicio.hxx> 50 #include <comphelper/container.hxx> 51 #include <comphelper/numbers.hxx> 52 #include <comphelper/listenernotification.hxx> 53 #include <connectivity/dbtools.hxx> 54 #include <connectivity/formattedcolumnvalue.hxx> 55 #include <connectivity/dbconversion.hxx> 56 #include <cppuhelper/queryinterface.hxx> 57 #include <rtl/logfile.hxx> 58 #include <tools/debug.hxx> 59 #include <tools/diagnose_ex.h> 60 #include <unotools/sharedunocomponent.hxx> 61 #include <vcl/svapp.hxx> 62 63 #include <boost/optional.hpp> 64 65 #include <algorithm> 66 #include <functional> 67 68 69 //......................................................................... 70 namespace frm 71 { 72 using namespace ::com::sun::star::uno; 73 using namespace ::com::sun::star::sdb; 74 using namespace ::com::sun::star::sdbc; 75 using namespace ::com::sun::star::sdbcx; 76 using namespace ::com::sun::star::beans; 77 using namespace ::com::sun::star::container; 78 using namespace ::com::sun::star::form; 79 using namespace ::com::sun::star::awt; 80 using namespace ::com::sun::star::io; 81 using namespace ::com::sun::star::lang; 82 using namespace ::com::sun::star::util; 83 using namespace ::com::sun::star::form::binding; 84 using namespace ::dbtools; 85 86 using ::connectivity::ORowSetValue; 87 88 //============================================================================== 89 //= helper 90 //============================================================================== 91 namespace 92 { 93 //-------------------------------------------------------------------------- 94 struct RowSetValueToString : public ::std::unary_function< ORowSetValue, ::rtl::OUString > 95 { operator ()frm::__anon805a10340111::RowSetValueToString96 ::rtl::OUString operator()( const ORowSetValue& _value ) const 97 { 98 return _value.getString(); 99 } 100 }; 101 102 //-------------------------------------------------------------------------- 103 struct AppendRowSetValueString : public ::std::unary_function< ::rtl::OUString, void > 104 { AppendRowSetValueStringfrm::__anon805a10340111::AppendRowSetValueString105 AppendRowSetValueString( ::rtl::OUString& _string ) 106 :m_string( _string ) 107 { 108 } 109 operator ()frm::__anon805a10340111::AppendRowSetValueString110 void operator()( const ::rtl::OUString _append ) 111 { 112 m_string += _append; 113 } 114 115 private: 116 ::rtl::OUString& m_string; 117 }; 118 119 //-------------------------------------------------------------------------- lcl_convertToStringSequence(const ValueList & _values)120 Sequence< ::rtl::OUString > lcl_convertToStringSequence( const ValueList& _values ) 121 { 122 Sequence< ::rtl::OUString > aStrings( _values.size() ); 123 ::std::transform( 124 _values.begin(), 125 _values.end(), 126 aStrings.getArray(), 127 RowSetValueToString() 128 ); 129 return aStrings; 130 } 131 } 132 133 //============================================================================== 134 //= ItemEventDescription 135 //============================================================================== 136 typedef ::comphelper::EventHolder< ItemEvent > ItemEventDescription; 137 138 //============================================================================== 139 //= OListBoxModel 140 //============================================================================== 141 //------------------------------------------------------------------ OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)142 InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) 143 { 144 return *(new OListBoxModel(_rxFactory)); 145 } 146 147 //------------------------------------------------------------------------------ _getTypes()148 Sequence< Type> OListBoxModel::_getTypes() 149 { 150 return TypeBag( 151 OBoundControlModel::_getTypes(), 152 OEntryListHelper::getTypes(), 153 OErrorBroadcaster::getTypes() 154 ).getTypes(); 155 } 156 157 158 DBG_NAME(OListBoxModel); 159 //------------------------------------------------------------------ OListBoxModel(const Reference<XMultiServiceFactory> & _rxFactory)160 OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) 161 :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True ) 162 // use the old control name for compytibility reasons 163 ,OEntryListHelper( (OControlModel&)*this ) 164 ,OErrorBroadcaster( OComponentHelper::rBHelper ) 165 ,m_aListRowSet( getContext() ) 166 ,m_nNULLPos(-1) 167 ,m_nBoundColumnType( DataType::SQLNULL ) 168 { 169 DBG_CTOR(OListBoxModel,NULL); 170 171 m_nClassId = FormComponentType::LISTBOX; 172 m_eListSourceType = ListSourceType_VALUELIST; 173 m_aBoundColumn <<= (sal_Int16)1; 174 initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ); 175 176 startAggregatePropertyListening( PROPERTY_STRINGITEMLIST ); 177 } 178 179 //------------------------------------------------------------------ OListBoxModel(const OListBoxModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)180 OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) 181 :OBoundControlModel( _pOriginal, _rxFactory ) 182 ,OEntryListHelper( *_pOriginal, (OControlModel&)*this ) 183 ,OErrorBroadcaster( OComponentHelper::rBHelper ) 184 ,m_aListRowSet( getContext() ) 185 ,m_eListSourceType( _pOriginal->m_eListSourceType ) 186 ,m_aBoundColumn( _pOriginal->m_aBoundColumn ) 187 ,m_aListSourceValues( _pOriginal->m_aListSourceValues ) 188 ,m_aBoundValues( _pOriginal->m_aBoundValues ) 189 ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq ) 190 ,m_nNULLPos(-1) 191 ,m_nBoundColumnType( DataType::SQLNULL ) 192 { 193 DBG_CTOR(OListBoxModel,NULL); 194 195 startAggregatePropertyListening( PROPERTY_STRINGITEMLIST ); 196 } 197 198 //------------------------------------------------------------------ ~OListBoxModel()199 OListBoxModel::~OListBoxModel() 200 { 201 if (!OComponentHelper::rBHelper.bDisposed) 202 { 203 acquire(); 204 dispose(); 205 } 206 207 DBG_DTOR(OListBoxModel,NULL); 208 } 209 210 // XCloneable 211 //------------------------------------------------------------------------------ IMPLEMENT_DEFAULT_CLONING(OListBoxModel)212 IMPLEMENT_DEFAULT_CLONING( OListBoxModel ) 213 214 // XServiceInfo 215 //------------------------------------------------------------------------------ 216 StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException) 217 { 218 StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); 219 220 sal_Int32 nOldLen = aSupported.getLength(); 221 aSupported.realloc( nOldLen + 8 ); 222 ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; 223 224 *pStoreTo++ = BINDABLE_CONTROL_MODEL; 225 *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; 226 *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; 227 228 *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; 229 *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; 230 231 *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX; 232 *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX; 233 *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX; 234 235 return aSupported; 236 } 237 238 //------------------------------------------------------------------------------ queryAggregation(const Type & _rType)239 Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException) 240 { 241 Any aReturn = OBoundControlModel::queryAggregation( _rType ); 242 if ( !aReturn.hasValue() ) 243 aReturn = OEntryListHelper::queryInterface( _rType ); 244 if ( !aReturn.hasValue() ) 245 aReturn = OErrorBroadcaster::queryInterface( _rType ); 246 return aReturn; 247 } 248 249 // OComponentHelper 250 //------------------------------------------------------------------------------ disposing()251 void OListBoxModel::disposing() 252 { 253 OBoundControlModel::disposing(); 254 OEntryListHelper::disposing(); 255 OErrorBroadcaster::disposing(); 256 } 257 258 //------------------------------------------------------------------------------ getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const259 void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const 260 { 261 switch (_nHandle) 262 { 263 case PROPERTY_ID_BOUNDCOLUMN: 264 _rValue <<= m_aBoundColumn; 265 break; 266 267 case PROPERTY_ID_LISTSOURCETYPE: 268 _rValue <<= m_eListSourceType; 269 break; 270 271 case PROPERTY_ID_LISTSOURCE: 272 _rValue <<= lcl_convertToStringSequence( m_aListSourceValues ); 273 break; 274 275 case PROPERTY_ID_VALUE_SEQ: 276 _rValue <<= lcl_convertToStringSequence( m_aBoundValues ); 277 break; 278 279 case PROPERTY_ID_DEFAULT_SELECT_SEQ: 280 _rValue <<= m_aDefaultSelectSeq; 281 break; 282 283 case PROPERTY_ID_STRINGITEMLIST: 284 _rValue <<= getStringItemList(); 285 break; 286 287 default: 288 OBoundControlModel::getFastPropertyValue(_rValue, _nHandle); 289 } 290 } 291 292 //------------------------------------------------------------------------------ setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)293 void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception) 294 { 295 switch (_nHandle) 296 { 297 case PROPERTY_ID_BOUNDCOLUMN : 298 DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID), 299 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 300 m_aBoundColumn = _rValue; 301 break; 302 303 case PROPERTY_ID_LISTSOURCETYPE : 304 DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType*>(NULL))), 305 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 306 _rValue >>= m_eListSourceType; 307 break; 308 309 case PROPERTY_ID_LISTSOURCE: 310 { 311 // extract 312 Sequence< ::rtl::OUString > aListSource; 313 OSL_VERIFY( _rValue >>= aListSource ); 314 315 // copy to member 316 ValueList().swap(m_aListSourceValues); 317 ::std::copy( 318 aListSource.getConstArray(), 319 aListSource.getConstArray() + aListSource.getLength(), 320 ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() ) 321 ); 322 323 // propagate 324 if ( m_eListSourceType == ListSourceType_VALUELIST ) 325 { 326 m_aBoundValues = m_aListSourceValues; 327 } 328 else 329 { 330 if ( m_xCursor.is() && !hasField() && !hasExternalListSource() ) 331 // listbox is already connected to a database, and no external list source 332 // data source changed -> refresh 333 loadData( false ); 334 } 335 } 336 break; 337 338 case PROPERTY_ID_VALUE_SEQ : 339 OSL_ENSURE( false, "ValueItemList is read-only!" ); 340 throw PropertyVetoException(); 341 342 case PROPERTY_ID_DEFAULT_SELECT_SEQ : 343 DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast< Sequence<sal_Int16>*>(NULL))), 344 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 345 _rValue >>= m_aDefaultSelectSeq; 346 347 DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !"); 348 if ( m_xAggregateFastSet.is() ) 349 setControlValue( _rValue, eOther ); 350 break; 351 352 case PROPERTY_ID_STRINGITEMLIST: 353 { 354 ControlModelLock aLock( *this ); 355 setNewStringItemList( _rValue, aLock ); 356 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only* 357 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with 358 // a lock - so we effectively has two locks here, of which setNewStringItemList can 359 // only control one. 360 } 361 resetNoBroadcast(); 362 break; 363 364 default: 365 OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); 366 } 367 } 368 369 //------------------------------------------------------------------------------ convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)370 sal_Bool OListBoxModel::convertFastPropertyValue( 371 Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) 372 throw (IllegalArgumentException) 373 { 374 sal_Bool bModified(sal_False); 375 switch (_nHandle) 376 { 377 case PROPERTY_ID_BOUNDCOLUMN : 378 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(reinterpret_cast<sal_Int16*>(NULL))); 379 break; 380 381 case PROPERTY_ID_LISTSOURCETYPE: 382 bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType); 383 break; 384 385 case PROPERTY_ID_LISTSOURCE: 386 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) ); 387 break; 388 389 case PROPERTY_ID_VALUE_SEQ : 390 OSL_ENSURE( false, "ValueItemList is read-only!" ); 391 throw PropertyVetoException(); 392 393 case PROPERTY_ID_DEFAULT_SELECT_SEQ : 394 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq); 395 break; 396 397 case PROPERTY_ID_STRINGITEMLIST: 398 bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue ); 399 break; 400 401 default: 402 return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); 403 } 404 return bModified; 405 } 406 407 //------------------------------------------------------------------------------ setPropertyValues(const Sequence<::rtl::OUString> & _rPropertyNames,const Sequence<Any> & _rValues)408 void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) 409 { 410 // if both SelectedItems and StringItemList are set, care for this 411 // #i27024# / 2004-04-05 / fs@openoffice.org 412 const Any* pSelectSequenceValue = NULL; 413 414 const ::rtl::OUString* pStartPos = _rPropertyNames.getConstArray(); 415 const ::rtl::OUString* pEndPos = _rPropertyNames.getConstArray() + _rPropertyNames.getLength(); 416 const ::rtl::OUString* pSelectedItemsPos = ::std::find_if( 417 pStartPos, pEndPos, 418 ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_SELECT_SEQ ) 419 ); 420 const ::rtl::OUString* pStringItemListPos = ::std::find_if( 421 pStartPos, pEndPos, 422 ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_STRINGITEMLIST ) 423 ); 424 if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) ) 425 { 426 // both properties are present 427 // -> remember the value for the select sequence 428 pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos ); 429 } 430 431 OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues ); 432 433 if ( pSelectSequenceValue ) 434 { 435 setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue ); 436 // Note that this is the only reliable way, since one of the properties is implemented 437 // by ourself, and one is implemented by the aggregate, we cannot rely on any particular 438 // results when setting them both - too many undocumented behavior in all the involved 439 // classes 440 } 441 } 442 443 //------------------------------------------------------------------------------ describeFixedProperties(Sequence<Property> & _rProps) const444 void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const 445 { 446 BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel ) 447 DECL_PROP1(TABINDEX, sal_Int16, BOUND); 448 DECL_PROP2(BOUNDCOLUMN, sal_Int16, BOUND, MAYBEVOID); 449 DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND); 450 DECL_PROP1(LISTSOURCE, StringSequence, BOUND); 451 DECL_PROP3(VALUE_SEQ, StringSequence, BOUND, READONLY, TRANSIENT); 452 DECL_PROP1(DEFAULT_SELECT_SEQ, Sequence<sal_Int16>, BOUND); 453 DECL_PROP1(STRINGITEMLIST, Sequence< ::rtl::OUString >, BOUND); 454 END_DESCRIBE_PROPERTIES(); 455 } 456 457 //------------------------------------------------------------------------------ _propertyChanged(const PropertyChangeEvent & i_rEvent)458 void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException ) 459 { 460 if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST ) 461 { 462 ControlModelLock aLock( *this ); 463 // SYNCHRONIZED -----> 464 // our aggregate internally changed its StringItemList property - reflect this in our "overridden" 465 // version of the property 466 setNewStringItemList( i_rEvent.NewValue, aLock ); 467 // <----- SYNCHRONIZED 468 return; 469 } 470 OBoundControlModel::_propertyChanged( i_rEvent ); 471 } 472 473 //------------------------------------------------------------------------------ describeAggregateProperties(Sequence<Property> & _rAggregateProps) const474 void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const 475 { 476 OBoundControlModel::describeAggregateProperties( _rAggregateProps ); 477 478 // superseded properties: 479 RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST ); 480 } 481 482 //------------------------------------------------------------------------------ getServiceName()483 ::rtl::OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException) 484 { 485 return FRM_COMPONENT_LISTBOX; // old (non-sun) name for compatibility ! 486 } 487 488 //------------------------------------------------------------------------------ write(const Reference<XObjectOutputStream> & _rxOutStream)489 void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream) 490 throw(IOException, RuntimeException) 491 { 492 OBoundControlModel::write(_rxOutStream); 493 494 // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird 495 Sequence<sal_Int16> aDummySeq; 496 497 // Version 498 // Version 0x0002: ListSource wird StringSeq 499 _rxOutStream->writeShort(0x0004); 500 501 // Maskierung fuer any 502 sal_uInt16 nAnyMask = 0; 503 if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID) 504 nAnyMask |= BOUNDCOLUMN; 505 506 _rxOutStream << nAnyMask; 507 508 _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues ); 509 _rxOutStream << (sal_Int16)m_eListSourceType; 510 _rxOutStream << aDummySeq; 511 _rxOutStream << m_aDefaultSelectSeq; 512 513 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) 514 { 515 sal_Int16 nBoundColumn = 0; 516 m_aBoundColumn >>= nBoundColumn; 517 _rxOutStream << nBoundColumn; 518 } 519 writeHelpTextCompatibly(_rxOutStream); 520 521 // from version 0x0004 : common properties 522 writeCommonProperties(_rxOutStream); 523 } 524 525 //------------------------------------------------------------------------------ read(const Reference<XObjectInputStream> & _rxInStream)526 void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) 527 { 528 // Bei manchen Variblen muessen Abhaengigkeiten beruecksichtigt werden. 529 // Deshalb muessen sie explizit ueber setPropertyValue() gesetzt werden. 530 531 OBoundControlModel::read(_rxInStream); 532 ControlModelLock aLock( *this ); 533 534 // since we are "overwriting" the StringItemList of our aggregate (means we have 535 // an own place to store the value, instead of relying on our aggregate storing it), 536 // we need to respect what the aggregate just read for the StringItemList property. 537 try 538 { 539 if ( m_xAggregateSet.is() ) 540 setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock ); 541 } 542 catch( const Exception& ) 543 { 544 OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" ); 545 } 546 547 // Version 548 sal_uInt16 nVersion = _rxInStream->readShort(); 549 DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !"); 550 551 if (nVersion > 0x0004) 552 { 553 DBG_ERROR("OListBoxModel::read : invalid (means unknown) version !"); 554 ValueList().swap(m_aListSourceValues); 555 m_aBoundColumn <<= (sal_Int16)0; 556 ValueList().swap(m_aBoundValues); 557 m_eListSourceType = ListSourceType_VALUELIST; 558 m_aDefaultSelectSeq.realloc(0); 559 defaultCommonProperties(); 560 return; 561 } 562 563 // Maskierung fuer any 564 sal_uInt16 nAnyMask; 565 _rxInStream >> nAnyMask; 566 567 // ListSourceSeq 568 StringSequence aListSourceSeq; 569 if (nVersion == 0x0001) 570 { 571 // ListSourceSeq aus String zusammenstellen; 572 ::rtl::OUString sListSource; 573 _rxInStream >> sListSource; 574 575 sal_Int32 nTokens = 1; 576 const sal_Unicode* pStr = sListSource.getStr(); 577 while ( *pStr ) 578 { 579 if ( *pStr == ';' ) 580 nTokens++; 581 pStr++; 582 } 583 aListSourceSeq.realloc( nTokens ); 584 for (sal_uInt16 i=0; i<nTokens; ++i) 585 { 586 sal_Int32 nTmp = 0; 587 aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp); 588 } 589 } 590 else 591 _rxInStream >> aListSourceSeq; 592 593 sal_Int16 nListSourceType; 594 _rxInStream >> nListSourceType; 595 m_eListSourceType = (ListSourceType)nListSourceType; 596 Any aListSourceSeqAny; 597 aListSourceSeqAny <<= aListSourceSeq; 598 599 setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny ); 600 601 // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird 602 Sequence<sal_Int16> aDummySeq; 603 _rxInStream >> aDummySeq; 604 605 // DefaultSelectSeq 606 Sequence<sal_Int16> aDefaultSelectSeq; 607 _rxInStream >> aDefaultSelectSeq; 608 Any aDefaultSelectSeqAny; 609 aDefaultSelectSeqAny <<= aDefaultSelectSeq; 610 setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny); 611 612 // BoundColumn 613 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) 614 { 615 sal_Int16 nValue; 616 _rxInStream >> nValue; 617 m_aBoundColumn <<= nValue; 618 } 619 620 if (nVersion > 2) 621 readHelpTextCompatibly(_rxInStream); 622 623 // if our string list is not filled from the value list, we must empty it 624 // this can be the case when somebody saves in alive mode 625 if ( ( m_eListSourceType != ListSourceType_VALUELIST ) 626 && !hasExternalListSource() 627 ) 628 { 629 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); 630 } 631 632 if (nVersion > 3) 633 readCommonProperties(_rxInStream); 634 635 // Nach dem Lesen die Defaultwerte anzeigen 636 if ( getControlSource().getLength() ) 637 // (not if we don't have a control source - the "State" property acts like it is persistent, then 638 resetNoBroadcast(); 639 } 640 641 //------------------------------------------------------------------------------ loadData(bool _bForce)642 void OListBoxModel::loadData( bool _bForce ) 643 { 644 RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" ); 645 DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" ); 646 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" ); 647 648 const sal_Int16 nNULLPosBackup( m_nNULLPos ); 649 const sal_Int32 nBoundColumnTypeBackup( m_nBoundColumnType ); 650 m_nNULLPos = -1; 651 m_nBoundColumnType = DataType::SQLNULL; 652 653 // pre-requisites: 654 // PRE1: connection 655 Reference< XConnection > xConnection; 656 // is the active connection of our form 657 Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY ); 658 if ( xFormProps.is() ) 659 xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection; 660 661 // PRE2: list source 662 ::rtl::OUString sListSource; 663 // if our list source type is no value list, we need to concatenate 664 // the single list source elements 665 ::std::for_each( 666 m_aListSourceValues.begin(), 667 m_aListSourceValues.end(), 668 AppendRowSetValueString( sListSource ) 669 ); 670 671 // outta here if we don't have all pre-requisites 672 if ( !xConnection.is() || !sListSource.getLength() ) 673 { 674 ValueList().swap(m_aBoundValues); 675 return; 676 } 677 678 ::boost::optional< sal_Int16 > aBoundColumn; 679 if ( m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT ) 680 { 681 sal_Int16 nBoundColumn( 0 ); 682 m_aBoundColumn >>= nBoundColumn; 683 aBoundColumn.reset( nBoundColumn ); 684 } 685 686 ::utl::SharedUNOComponent< XResultSet > xListCursor; 687 try 688 { 689 m_aListRowSet.setConnection( xConnection ); 690 691 sal_Bool bExecute = sal_False; 692 switch (m_eListSourceType) 693 { 694 case ListSourceType_TABLEFIELDS: 695 // don't work with a statement here, the fields will be collected below 696 break; 697 698 case ListSourceType_TABLE: 699 { 700 Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource); 701 Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY); 702 703 // do we have a bound column if yes we have to select it 704 // and the displayed column is the first column othwhise we act as a combobox 705 ::rtl::OUString aFieldName; 706 ::rtl::OUString aBoundFieldName; 707 708 if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && xFieldsByIndex.is() ) 709 { 710 if ( *aBoundColumn >= xFieldsByIndex->getCount() ) 711 break; 712 713 Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex( *aBoundColumn ),UNO_QUERY); 714 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName; 715 aBoundColumn.reset( 1 ); 716 717 xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY); 718 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName; 719 } 720 else if (xFieldsByName.is()) 721 { 722 if ( xFieldsByName->hasByName( getControlSource() ) ) 723 aFieldName = getControlSource(); 724 else 725 { 726 // otherwise look for the alias 727 Reference< XColumnsSupplier > xSupplyFields; 728 xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSupplyFields; 729 730 // search the field 731 DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !"); 732 733 Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns(); 734 if ( xFieldNames->hasByName( getControlSource() ) ) 735 { 736 Reference<XPropertySet> xComposerFieldAsSet; 737 xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet; 738 if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet)) 739 xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName; 740 } 741 } 742 } 743 if (!aFieldName.getLength()) 744 break; 745 746 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); 747 ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); 748 ::rtl::OUString aStatement = ::rtl::OUString::createFromAscii("SELECT "); 749 if (!aBoundFieldName.getLength()) // act like a combobox 750 aStatement += ::rtl::OUString::createFromAscii("DISTINCT "); 751 752 aStatement += quoteName(aQuote,aFieldName); 753 if (aBoundFieldName.getLength()) 754 { 755 aStatement += ::rtl::OUString::createFromAscii(", "); 756 aStatement += quoteName(aQuote, aBoundFieldName); 757 } 758 aStatement += ::rtl::OUString::createFromAscii(" FROM "); 759 760 ::rtl::OUString sCatalog, sSchema, sTable; 761 qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation ); 762 aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ); 763 764 m_aListRowSet.setEscapeProcessing( sal_False ); 765 m_aListRowSet.setCommand( aStatement ); 766 bExecute = sal_True; 767 } 768 break; 769 770 case ListSourceType_QUERY: 771 m_aListRowSet.setCommandFromQuery( sListSource ); 772 bExecute = sal_True; 773 break; 774 775 default: 776 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType ); 777 m_aListRowSet.setCommand( sListSource ); 778 bExecute = sal_True; 779 break; 780 } 781 782 if (bExecute) 783 { 784 if ( !_bForce && !m_aListRowSet.isDirty() ) 785 { 786 // if none of the settings of the row set changed, compared to the last 787 // invocation of loadData, then don't re-fill the list. Instead, assume 788 // the list entries are the same. 789 m_nNULLPos = nNULLPosBackup; 790 m_nBoundColumnType = nBoundColumnTypeBackup; 791 return; 792 } 793 xListCursor.reset( m_aListRowSet.execute() ); 794 } 795 } 796 catch(SQLException& eSQL) 797 { 798 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); 799 return; 800 } 801 catch(const Exception& eUnknown) 802 { 803 (void)eUnknown; 804 return; 805 } 806 807 // Anzeige- und Werteliste fuellen 808 ValueList aDisplayList, aValueList; 809 sal_Bool bUseNULL = hasField() && !isRequired(); 810 811 try 812 { 813 OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ), 814 "OListBoxModel::loadData: logic error!" ); 815 if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) ) 816 return; 817 818 switch (m_eListSourceType) 819 { 820 case ListSourceType_SQL: 821 case ListSourceType_SQLPASSTHROUGH: 822 case ListSourceType_TABLE: 823 case ListSourceType_QUERY: 824 { 825 // Feld der 1. Column des ResultSets holen 826 Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY); 827 DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!"); 828 Reference<XIndexAccess> xColumns; 829 if (xSupplyCols.is()) 830 { 831 xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY); 832 DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !"); 833 } 834 835 Reference< XPropertySet > xDataField; 836 if ( xColumns.is() ) 837 xColumns->getByIndex(0) >>= xDataField; 838 if ( !xDataField.is() ) 839 return; 840 841 ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField ); 842 843 // Feld der BoundColumn des ResultSets holen 844 m_nBoundColumnType = DataType::SQLNULL; 845 if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && m_xColumn.is() ) 846 { // don't look for a bound column if we're not connected to a field 847 try 848 { 849 Reference< XPropertySet > xBoundField( xColumns->getByIndex( *aBoundColumn ), UNO_QUERY_THROW ); 850 OSL_VERIFY( xBoundField->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= m_nBoundColumnType ); 851 } 852 catch( const Exception& ) 853 { 854 DBG_UNHANDLED_EXCEPTION(); 855 } 856 } 857 858 // Ist die LB an ein Feld gebunden und sind Leereintraege zulaessig 859 // dann wird die Position fuer einen Leereintrag gemerkt 860 861 RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" ); 862 ::rtl::OUString aStr; 863 sal_Int16 entryPos = 0; 864 ORowSetValue aBoundValue; 865 Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW ); 866 while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries 867 { 868 aStr = aValueFormatter.getFormattedValue(); 869 aDisplayList.push_back( aStr ); 870 871 if ( impl_hasBoundComponent() ) 872 { 873 aBoundValue.fill( *aBoundColumn + 1, m_nBoundColumnType, xCursorRow ); 874 aValueList.push_back( aBoundValue ); 875 } 876 877 if ( bUseNULL && ( m_nNULLPos == -1 ) && !aStr.getLength() ) 878 m_nNULLPos = sal_Int16( aDisplayList.size() - 1 ); 879 } 880 } 881 break; 882 883 case ListSourceType_TABLEFIELDS: 884 { 885 Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource); 886 if (xFieldNames.is()) 887 { 888 StringSequence seqNames = xFieldNames->getElementNames(); 889 ::std::copy( 890 seqNames.getConstArray(), 891 seqNames.getConstArray() + seqNames.getLength(), 892 ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() ) 893 ); 894 } 895 } 896 break; 897 default: 898 OSL_ENSURE( false, "OListBoxModel::loadData: unreachable!" ); 899 break; 900 } 901 } 902 catch(SQLException& eSQL) 903 { 904 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); 905 return; 906 } 907 catch( const Exception& ) 908 { 909 DBG_UNHANDLED_EXCEPTION(); 910 return; 911 } 912 913 914 // Value-Sequence erzeugen 915 // NULL eintrag hinzufuegen 916 if (bUseNULL && m_nNULLPos == -1) 917 { 918 if ( impl_hasBoundComponent() ) 919 aValueList.insert( aValueList.begin(), ORowSetValue() ); 920 921 aDisplayList.insert( aDisplayList.begin(), ORowSetValue( ::rtl::OUString() ) ); 922 m_nNULLPos = 0; 923 } 924 925 m_aBoundValues = aValueList; 926 927 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) ); 928 } 929 930 //------------------------------------------------------------------------------ onConnectedDbColumn(const Reference<XInterface> &)931 void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) 932 { 933 // list boxes which are bound to a db column don't have multi selection 934 // - this would be unable to reflect in the db column 935 if ( hasField() ) 936 { 937 setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) ); 938 } 939 940 if ( !hasExternalListSource() ) 941 impl_refreshDbEntryList( false ); 942 } 943 944 //------------------------------------------------------------------------------ onDisconnectedDbColumn()945 void OListBoxModel::onDisconnectedDbColumn() 946 { 947 if ( m_eListSourceType != ListSourceType_VALUELIST ) 948 { 949 ValueList().swap(m_aBoundValues); 950 m_nNULLPos = -1; 951 m_nBoundColumnType = DataType::SQLNULL; 952 953 if ( !hasExternalListSource() ) 954 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); 955 956 m_aListRowSet.dispose(); 957 } 958 } 959 960 //------------------------------------------------------------------------------ impl_getValues() const961 ValueList OListBoxModel::impl_getValues() const 962 { 963 if ( !m_aBoundValues.empty() ) 964 return m_aBoundValues; 965 966 Sequence< ::rtl::OUString > aStringItems( getStringItemList() ); 967 ValueList aValues( aStringItems.getLength() ); 968 ::std::copy( 969 aStringItems.getConstArray(), 970 aStringItems.getConstArray() + aStringItems.getLength(), 971 aValues.begin() 972 ); 973 974 return aValues; 975 } 976 //------------------------------------------------------------------------------ getFirstSelectedValue() const977 ORowSetValue OListBoxModel::getFirstSelectedValue() const 978 { 979 static const ORowSetValue s_aEmptyVaue; 980 981 DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" ); 982 if ( !m_xAggregateFastSet.is() ) 983 return s_aEmptyVaue; 984 985 Sequence< sal_Int16 > aSelectedIndices; 986 OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices ); 987 if ( !aSelectedIndices.getLength() ) 988 // nothing selected at all 989 return s_aEmptyVaue; 990 991 if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) ) 992 // the dedicated "NULL" entry is selected 993 return s_aEmptyVaue; 994 995 ValueList aValues( impl_getValues() ); 996 997 size_t selectedValue = aSelectedIndices[0]; 998 if ( selectedValue >= aValues.size() ) 999 { 1000 OSL_ENSURE( false, "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" ); 1001 return s_aEmptyVaue; 1002 } 1003 1004 return aValues[ selectedValue ]; 1005 } 1006 1007 //------------------------------------------------------------------------------ commitControlValueToDbColumn(bool)1008 sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) 1009 { 1010 // current selektion list 1011 const ORowSetValue aCurrentValue( getFirstSelectedValue() ); 1012 if ( aCurrentValue != m_aSaveValue ) 1013 { 1014 if ( aCurrentValue.isNull() ) 1015 m_xColumnUpdate->updateNull(); 1016 else 1017 { 1018 try 1019 { 1020 m_xColumnUpdate->updateObject( aCurrentValue.makeAny() ); 1021 } 1022 catch ( const Exception& ) 1023 { 1024 return sal_False; 1025 } 1026 } 1027 m_aSaveValue = aCurrentValue; 1028 } 1029 return sal_True; 1030 } 1031 1032 // XPropertiesChangeListener 1033 //------------------------------------------------------------------------------ translateDbColumnToControlValue()1034 Any OListBoxModel::translateDbColumnToControlValue() 1035 { 1036 Reference< XPropertySet > xBoundField( getField() ); 1037 if ( !xBoundField.is() ) 1038 { 1039 OSL_ENSURE( false, "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" ); 1040 return Any(); 1041 } 1042 1043 Sequence< sal_Int16 > aSelectionIndicies; 1044 1045 ORowSetValue aCurrentValue; 1046 aCurrentValue.fill( impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType(), m_xColumn ); 1047 1048 // reset selection for NULL values 1049 if ( aCurrentValue.isNull() ) 1050 { 1051 if ( m_nNULLPos != -1 ) 1052 { 1053 aSelectionIndicies.realloc(1); 1054 aSelectionIndicies[0] = m_nNULLPos; 1055 } 1056 } 1057 else 1058 { 1059 ValueList aValues( impl_getValues() ); 1060 ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), aCurrentValue ); 1061 if ( curValuePos != aValues.end() ) 1062 { 1063 aSelectionIndicies.realloc( 1 ); 1064 aSelectionIndicies[0] = curValuePos - aValues.begin(); 1065 } 1066 } 1067 1068 m_aSaveValue = aCurrentValue; 1069 1070 return makeAny( aSelectionIndicies ); 1071 } 1072 1073 // XReset 1074 //------------------------------------------------------------------------------ getDefaultForReset() const1075 Any OListBoxModel::getDefaultForReset() const 1076 { 1077 Any aValue; 1078 if (m_aDefaultSelectSeq.getLength()) 1079 aValue <<= m_aDefaultSelectSeq; 1080 else if (m_nNULLPos != -1) // gebundene Listbox 1081 { 1082 Sequence<sal_Int16> aSeq(1); 1083 aSeq.getArray()[0] = m_nNULLPos; 1084 aValue <<= aSeq; 1085 } 1086 else 1087 { 1088 Sequence<sal_Int16> aSeq; 1089 aValue <<= aSeq; 1090 } 1091 1092 return aValue; 1093 } 1094 1095 //-------------------------------------------------------------------- resetNoBroadcast()1096 void OListBoxModel::resetNoBroadcast() 1097 { 1098 OBoundControlModel::resetNoBroadcast(); 1099 m_aSaveValue.setNull(); 1100 } 1101 1102 //-------------------------------------------------------------------- disposing(const EventObject & _rSource)1103 void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException ) 1104 { 1105 if ( !OEntryListHelper::handleDisposing( _rSource ) ) 1106 OBoundControlModel::disposing( _rSource ); 1107 } 1108 1109 //-------------------------------------------------------------------- 1110 namespace 1111 { 1112 /** type how we should transfer our selection to external value bindings 1113 */ 1114 enum ExchangeType 1115 { 1116 eIndexList, /// as list of indexes of selected entries 1117 eIndex, /// as index of the selected entry 1118 eEntryList, /// as list of string representations of selected entries 1119 eEntry /// as string representation of the selected entry 1120 }; 1121 1122 //-------------------------------------------------------------------- lcl_getCurrentExchangeType(const Type & _rExchangeType)1123 ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType ) 1124 { 1125 switch ( _rExchangeType.getTypeClass() ) 1126 { 1127 case TypeClass_STRING: 1128 return eEntry; 1129 case TypeClass_LONG: 1130 return eIndex; 1131 case TypeClass_SEQUENCE: 1132 { 1133 Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType ); 1134 switch ( aElementType.getTypeClass() ) 1135 { 1136 case TypeClass_STRING: 1137 return eEntryList; 1138 case TypeClass_LONG: 1139 return eIndexList; 1140 default: 1141 break; 1142 } 1143 } 1144 default: 1145 break; 1146 } 1147 OSL_ENSURE( false, "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" ); 1148 return eEntry; 1149 } 1150 } 1151 1152 //-------------------------------------------------------------------- translateExternalValueToControlValue(const Any & _rExternalValue) const1153 Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const 1154 { 1155 Sequence< sal_Int16 > aSelectIndexes; 1156 1157 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) 1158 { 1159 case eIndexList: 1160 { 1161 // unfortunately, our select sequence is a sequence<short>, while the external binding 1162 // supplies sequence<int> only -> transform this 1163 Sequence< sal_Int32 > aSelectIndexesPure; 1164 OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure ); 1165 aSelectIndexes.realloc( aSelectIndexesPure.getLength() ); 1166 ::std::copy( 1167 aSelectIndexesPure.getConstArray(), 1168 aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(), 1169 aSelectIndexes.getArray() 1170 ); 1171 } 1172 break; 1173 1174 case eIndex: 1175 { 1176 sal_Int32 nSelectIndex = -1; 1177 OSL_VERIFY( _rExternalValue >>= nSelectIndex ); 1178 if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) ) 1179 { 1180 aSelectIndexes.realloc( 1 ); 1181 aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex ); 1182 } 1183 } 1184 break; 1185 1186 case eEntryList: 1187 { 1188 // we can retrieve a string list from the binding for multiple selection 1189 Sequence< ::rtl::OUString > aSelectEntries; 1190 OSL_VERIFY( _rExternalValue >>= aSelectEntries ); 1191 1192 ::std::set< sal_Int16 > aSelectionSet; 1193 1194 // find the selection entries in our item list 1195 const ::rtl::OUString* pSelectEntries = aSelectEntries.getArray(); 1196 const ::rtl::OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength(); 1197 while ( pSelectEntries != pSelectEntriesEnd ) 1198 { 1199 // the indexes where the current string appears in our string items 1200 Sequence< sal_Int16 > aThisEntryIndexes; 1201 aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False ); 1202 1203 // insert all the indexes of this entry into our set 1204 ::std::copy( 1205 aThisEntryIndexes.getConstArray(), 1206 aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(), 1207 ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() ) 1208 ); 1209 } 1210 1211 // copy the indexes to the sequence 1212 aSelectIndexes.realloc( aSelectionSet.size() ); 1213 ::std::copy( 1214 aSelectionSet.begin(), 1215 aSelectionSet.end(), 1216 aSelectIndexes.getArray() 1217 ); 1218 } 1219 break; 1220 1221 case eEntry: 1222 { 1223 ::rtl::OUString sStringToSelect; 1224 OSL_VERIFY( _rExternalValue >>= sStringToSelect ); 1225 1226 aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False ); 1227 } 1228 break; 1229 } 1230 1231 return makeAny( aSelectIndexes ); 1232 } 1233 1234 //-------------------------------------------------------------------- 1235 namespace 1236 { 1237 //................................................................ 1238 struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, ::rtl::OUString > 1239 { 1240 protected: 1241 const Sequence< ::rtl::OUString >& m_rList; 1242 1243 public: ExtractStringFromSequence_Safefrm::__anon805a10340311::ExtractStringFromSequence_Safe1244 ExtractStringFromSequence_Safe( const Sequence< ::rtl::OUString >& _rList ) : m_rList( _rList ) { } 1245 operator ()frm::__anon805a10340311::ExtractStringFromSequence_Safe1246 ::rtl::OUString operator ()( sal_Int16 _nIndex ) 1247 { 1248 OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" ); 1249 if ( _nIndex < m_rList.getLength() ) 1250 return m_rList[ _nIndex ]; 1251 return ::rtl::OUString(); 1252 } 1253 }; 1254 1255 //................................................................ lcl_getSingleSelectedEntry(const Sequence<sal_Int16> & _rSelectSequence,const Sequence<::rtl::OUString> & _rStringList)1256 Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) 1257 { 1258 Any aReturn; 1259 1260 // by definition, multiple selected entries are transfered as NULL if the 1261 // binding does not support string lists 1262 if ( _rSelectSequence.getLength() <= 1 ) 1263 { 1264 ::rtl::OUString sSelectedEntry; 1265 1266 if ( _rSelectSequence.getLength() == 1 ) 1267 sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] ); 1268 1269 aReturn <<= sSelectedEntry; 1270 } 1271 1272 return aReturn; 1273 } 1274 1275 //................................................................ lcl_getMultiSelectedEntries(const Sequence<sal_Int16> & _rSelectSequence,const Sequence<::rtl::OUString> & _rStringList)1276 Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) 1277 { 1278 Sequence< ::rtl::OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() ); 1279 ::std::transform( 1280 _rSelectSequence.getConstArray(), 1281 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(), 1282 aSelectedEntriesTexts.getArray(), 1283 ExtractStringFromSequence_Safe( _rStringList ) 1284 ); 1285 return makeAny( aSelectedEntriesTexts ); 1286 } 1287 } 1288 1289 //-------------------------------------------------------------------- translateControlValueToExternalValue() const1290 Any OListBoxModel::translateControlValueToExternalValue( ) const 1291 { 1292 OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" ); 1293 1294 Sequence< sal_Int16 > aSelectSequence; 1295 const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence; 1296 1297 Any aReturn; 1298 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) 1299 { 1300 case eIndexList: 1301 { 1302 // unfortunately, the select sequence is a sequence<short>, but our binding 1303 // expects int's 1304 Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() ); 1305 ::std::copy( 1306 aSelectSequence.getConstArray(), 1307 aSelectSequence.getConstArray() + aSelectSequence.getLength(), 1308 aTransformed.getArray() 1309 ); 1310 aReturn <<= aTransformed; 1311 } 1312 break; 1313 1314 case eIndex: 1315 if ( aSelectSequence.getLength() <= 1 ) 1316 { 1317 sal_Int32 nIndex = -1; 1318 1319 if ( aSelectSequence.getLength() == 1 ) 1320 nIndex = aSelectSequence[0]; 1321 1322 aReturn <<= nIndex; 1323 } 1324 break; 1325 1326 case eEntryList: 1327 aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); 1328 break; 1329 1330 case eEntry: 1331 aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); 1332 break; 1333 } 1334 1335 return aReturn; 1336 } 1337 1338 //-------------------------------------------------------------------- getCurrentFormComponentValue() const1339 Any OListBoxModel::getCurrentFormComponentValue() const 1340 { 1341 if ( hasValidator() ) 1342 return OBoundControlModel::getCurrentFormComponentValue(); 1343 1344 Any aCurretnValue; 1345 1346 try 1347 { 1348 Sequence< sal_Int16 > aSelectSequence; 1349 OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence ); 1350 1351 sal_Bool bMultiSelection( sal_False ); 1352 OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection ); 1353 1354 if ( bMultiSelection ) 1355 aCurretnValue = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); 1356 else 1357 aCurretnValue = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); 1358 } 1359 catch( const Exception& ) 1360 { 1361 DBG_UNHANDLED_EXCEPTION(); 1362 } 1363 1364 return aCurretnValue; 1365 } 1366 1367 //-------------------------------------------------------------------- getSupportedBindingTypes()1368 Sequence< Type > OListBoxModel::getSupportedBindingTypes() 1369 { 1370 Sequence< Type > aTypes(4); 1371 aTypes[0] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) ); 1372 aTypes[1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); 1373 aTypes[2] = ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) ); 1374 aTypes[3] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); 1375 return aTypes; 1376 } 1377 1378 //-------------------------------------------------------------------- stringItemListChanged(ControlModelLock & _rInstanceLock)1379 void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock ) 1380 { 1381 if ( !m_xAggregateSet.is() ) 1382 return; 1383 1384 suspendValueListening(); 1385 try 1386 { 1387 m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) ); 1388 } 1389 catch( const Exception& ) 1390 { 1391 DBG_UNHANDLED_EXCEPTION(); 1392 } 1393 resumeValueListening(); 1394 1395 // update the selection here 1396 if ( hasExternalValueBinding( ) ) 1397 transferExternalValueToControl( _rInstanceLock ); 1398 else 1399 { 1400 if ( hasField() ) 1401 { 1402 // TODO: update the selection in case we're bound to a database column 1403 } 1404 else 1405 { 1406 if ( m_aDefaultSelectSeq.getLength() ) 1407 setControlValue( makeAny( m_aDefaultSelectSeq ), eOther ); 1408 } 1409 } 1410 } 1411 1412 //-------------------------------------------------------------------- connectedExternalListSource()1413 void OListBoxModel::connectedExternalListSource( ) 1414 { 1415 // TODO? 1416 } 1417 1418 //-------------------------------------------------------------------- disconnectedExternalListSource()1419 void OListBoxModel::disconnectedExternalListSource( ) 1420 { 1421 // TODO: in case we're part of an already loaded form, we should probably simulate 1422 // an onConnectedDbColumn, so our list get's filled with the data as indicated 1423 // by our SQL-binding related properties 1424 } 1425 1426 //-------------------------------------------------------------------- impl_refreshDbEntryList(bool _bForce)1427 void OListBoxModel::impl_refreshDbEntryList( bool _bForce ) 1428 { 1429 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" ); 1430 1431 if ( !hasExternalListSource( ) 1432 && ( m_eListSourceType != ListSourceType_VALUELIST ) 1433 && ( m_xCursor.is() ) 1434 ) 1435 { 1436 loadData( _bForce ); 1437 } 1438 } 1439 1440 //-------------------------------------------------------------------- refreshInternalEntryList()1441 void OListBoxModel::refreshInternalEntryList() 1442 { 1443 impl_refreshDbEntryList( true ); 1444 if ( hasField() && m_xCursor.is() ) 1445 initFromField( m_xCursor ); 1446 } 1447 1448 //================================================================== 1449 // OListBoxControl 1450 //================================================================== 1451 1452 //------------------------------------------------------------------ OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)1453 InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) 1454 { 1455 return *(new OListBoxControl(_rxFactory)); 1456 } 1457 1458 //------------------------------------------------------------------------------ _getTypes()1459 Sequence< Type> OListBoxControl::_getTypes() 1460 { 1461 return TypeBag( 1462 OBoundControl::_getTypes(), 1463 OListBoxControl_BASE::getTypes() 1464 ).getTypes(); 1465 } 1466 1467 //------------------------------------------------------------------ queryAggregation(const Type & _rType)1468 Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException) 1469 { 1470 Any aReturn = OListBoxControl_BASE::queryInterface( _rType ); 1471 1472 if ( !aReturn.hasValue() 1473 || _rType.equals( XTypeProvider::static_type() ) 1474 ) 1475 aReturn = OBoundControl::queryAggregation( _rType ); 1476 1477 return aReturn; 1478 } 1479 1480 DBG_NAME(OListBoxControl); 1481 //------------------------------------------------------------------------------ OListBoxControl(const Reference<XMultiServiceFactory> & _rxFactory)1482 OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) 1483 :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False ) 1484 ,m_aChangeListeners( m_aMutex ) 1485 ,m_aItemListeners( m_aMutex ) 1486 ,m_pItemBroadcaster( NULL ) 1487 { 1488 DBG_CTOR(OListBoxControl,NULL); 1489 1490 increment(m_refCount); 1491 { 1492 // als FocusListener anmelden 1493 Reference<XWindow> xComp; 1494 if (query_aggregation(m_xAggregate, xComp)) 1495 xComp->addFocusListener(this); 1496 1497 // als ItemListener anmelden 1498 if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) ) 1499 m_xAggregateListBox->addItemListener(this); 1500 } 1501 // Refcount bei 2 fuer angemeldete Listener 1502 decrement(m_refCount); 1503 1504 doSetDelegator(); 1505 1506 m_aChangeTimer.SetTimeout(500); 1507 m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout)); 1508 } 1509 1510 //------------------------------------------------------------------------------ ~OListBoxControl()1511 OListBoxControl::~OListBoxControl() 1512 { 1513 if (!OComponentHelper::rBHelper.bDisposed) 1514 { 1515 acquire(); 1516 dispose(); 1517 } 1518 1519 doResetDelegator(); 1520 m_xAggregateListBox.clear(); 1521 1522 DBG_DTOR(OListBoxControl,NULL); 1523 } 1524 1525 //------------------------------------------------------------------------------ getSupportedServiceNames()1526 StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException) 1527 { 1528 StringSequence aSupported = OBoundControl::getSupportedServiceNames(); 1529 aSupported.realloc(aSupported.getLength() + 1); 1530 1531 ::rtl::OUString* pArray = aSupported.getArray(); 1532 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX; 1533 return aSupported; 1534 } 1535 1536 1537 // XFocusListener 1538 //------------------------------------------------------------------------------ focusGained(const FocusEvent &)1539 void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException) 1540 { 1541 ::osl::MutexGuard aGuard(m_aMutex); 1542 if ( m_aChangeListeners.getLength() ) // only if there are listeners 1543 { 1544 Reference<XPropertySet> xSet(getModel(), UNO_QUERY); 1545 if (xSet.is()) 1546 { 1547 // memorize the current selection for posting the change event 1548 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); 1549 } 1550 } 1551 } 1552 1553 //------------------------------------------------------------------------------ focusLost(const FocusEvent &)1554 void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException) 1555 { 1556 m_aCurrentSelection.clear(); 1557 } 1558 1559 // XItemListener 1560 //------------------------------------------------------------------------------ itemStateChanged(const ItemEvent & _rEvent)1561 void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException) 1562 { 1563 // forward this to our listeners 1564 { 1565 ::osl::MutexGuard aGuard( m_aMutex ); 1566 if ( m_aItemListeners.getLength() ) 1567 { 1568 if ( !m_pItemBroadcaster.is() ) 1569 { 1570 m_pItemBroadcaster.set( new ::comphelper::AsyncEventNotifier ); 1571 m_pItemBroadcaster->create(); 1572 } 1573 m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this ); 1574 } 1575 } 1576 1577 // and do the handling for the ChangeListeners 1578 ::osl::ClearableMutexGuard aGuard(m_aMutex); 1579 if ( m_aChangeTimer.IsActive() ) 1580 { 1581 Reference<XPropertySet> xSet(getModel(), UNO_QUERY); 1582 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); 1583 1584 m_aChangeTimer.Stop(); 1585 m_aChangeTimer.Start(); 1586 } 1587 else 1588 { 1589 if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() ) 1590 { 1591 Reference<XPropertySet> xSet(getModel(), UNO_QUERY); 1592 if (xSet.is()) 1593 { 1594 // Has the selection been changed? 1595 sal_Bool bModified(sal_False); 1596 Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); 1597 1598 Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue(); 1599 Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue(); 1600 sal_Int32 nLen = rSelection.getLength(); 1601 if (nLen != rOldSelection.getLength()) 1602 bModified = sal_True; 1603 else 1604 { 1605 const sal_Int16* pVal = rSelection.getConstArray(); 1606 const sal_Int16* pCompVal = rOldSelection.getConstArray(); 1607 1608 while (nLen-- && !bModified) 1609 bModified = pVal[nLen] != pCompVal[nLen]; 1610 } 1611 1612 if (bModified) 1613 { 1614 m_aCurrentSelection = aValue; 1615 m_aChangeTimer.Start(); 1616 } 1617 } 1618 } 1619 else if (m_aCurrentSelection.hasValue()) 1620 m_aCurrentSelection.clear(); 1621 } 1622 } 1623 1624 // XEventListener 1625 //------------------------------------------------------------------------------ disposing(const EventObject & _rSource)1626 void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException) 1627 { 1628 OBoundControl::disposing(_rSource); 1629 } 1630 1631 // XChangeBroadcaster 1632 //------------------------------------------------------------------------------ addChangeListener(const Reference<XChangeListener> & _rxListener)1633 void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) 1634 { 1635 m_aChangeListeners.addInterface( _rxListener ); 1636 } 1637 1638 //------------------------------------------------------------------------------ removeChangeListener(const Reference<XChangeListener> & _rxListener)1639 void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) 1640 { 1641 m_aChangeListeners.removeInterface( _rxListener ); 1642 } 1643 1644 // OComponentHelper 1645 //------------------------------------------------------------------------------ disposing()1646 void OListBoxControl::disposing() 1647 { 1648 if (m_aChangeTimer.IsActive()) 1649 m_aChangeTimer.Stop(); 1650 1651 EventObject aEvent( *this ); 1652 m_aChangeListeners.disposeAndClear( aEvent ); 1653 m_aItemListeners.disposeAndClear( aEvent ); 1654 1655 { 1656 ::osl::MutexGuard aGuard( m_aMutex ); 1657 if ( m_pItemBroadcaster.is() ) 1658 { 1659 m_pItemBroadcaster->removeEventsForProcessor( this ); 1660 m_pItemBroadcaster->terminate(); 1661 m_pItemBroadcaster = NULL; 1662 } 1663 } 1664 1665 OBoundControl::disposing(); 1666 } 1667 1668 //------------------------------------------------------------------------------ processEvent(const AnyEvent & _rEvent)1669 void OListBoxControl::processEvent( const AnyEvent& _rEvent ) 1670 { 1671 Reference< XListBox > xKeepAlive( this ); 1672 { 1673 ::osl::MutexGuard aGuard( m_aMutex ); 1674 if ( OComponentHelper::rBHelper.bDisposed ) 1675 return; 1676 } 1677 const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent ); 1678 m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() ); 1679 } 1680 1681 //------------------------------------------------------------------------------ 1682 IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/) 1683 { 1684 m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) ); 1685 return 0L; 1686 } 1687 1688 //-------------------------------------------------------------------- addItemListener(const Reference<XItemListener> & l)1689 void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) 1690 { 1691 m_aItemListeners.addInterface( l ); 1692 } 1693 1694 //-------------------------------------------------------------------- removeItemListener(const Reference<XItemListener> & l)1695 void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) 1696 { 1697 m_aItemListeners.removeInterface( l ); 1698 } 1699 1700 //-------------------------------------------------------------------- addActionListener(const Reference<XActionListener> & l)1701 void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) 1702 { 1703 if ( m_xAggregateListBox.is() ) 1704 m_xAggregateListBox->addActionListener( l ); 1705 } 1706 1707 //-------------------------------------------------------------------- removeActionListener(const Reference<XActionListener> & l)1708 void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) 1709 { 1710 if ( m_xAggregateListBox.is() ) 1711 m_xAggregateListBox->removeActionListener( l ); 1712 } 1713 1714 //-------------------------------------------------------------------- addItem(const::rtl::OUString & aItem,::sal_Int16 nPos)1715 void SAL_CALL OListBoxControl::addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException) 1716 { 1717 if ( m_xAggregateListBox.is() ) 1718 m_xAggregateListBox->addItem( aItem, nPos ); 1719 } 1720 1721 //-------------------------------------------------------------------- addItems(const Sequence<::rtl::OUString> & aItems,::sal_Int16 nPos)1722 void SAL_CALL OListBoxControl::addItems( const Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException) 1723 { 1724 if ( m_xAggregateListBox.is() ) 1725 m_xAggregateListBox->addItems( aItems, nPos ); 1726 } 1727 1728 //-------------------------------------------------------------------- removeItems(::sal_Int16 nPos,::sal_Int16 nCount)1729 void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException) 1730 { 1731 if ( m_xAggregateListBox.is() ) 1732 m_xAggregateListBox->removeItems( nPos, nCount ); 1733 } 1734 1735 //-------------------------------------------------------------------- getItemCount()1736 ::sal_Int16 SAL_CALL OListBoxControl::getItemCount( ) throw (RuntimeException) 1737 { 1738 if ( m_xAggregateListBox.is() ) 1739 return m_xAggregateListBox->getItemCount(); 1740 return 0; 1741 } 1742 1743 //-------------------------------------------------------------------- getItem(::sal_Int16 nPos)1744 ::rtl::OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException) 1745 { 1746 if ( m_xAggregateListBox.is() ) 1747 return m_xAggregateListBox->getItem( nPos ); 1748 return ::rtl::OUString( ); 1749 } 1750 1751 //-------------------------------------------------------------------- getItems()1752 Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getItems( ) throw (RuntimeException) 1753 { 1754 if ( m_xAggregateListBox.is() ) 1755 return m_xAggregateListBox->getItems(); 1756 return Sequence< ::rtl::OUString >( ); 1757 } 1758 1759 //-------------------------------------------------------------------- getSelectedItemPos()1760 ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos( ) throw (RuntimeException) 1761 { 1762 if ( m_xAggregateListBox.is() ) 1763 return m_xAggregateListBox->getSelectedItemPos(); 1764 return 0; 1765 } 1766 1767 //-------------------------------------------------------------------- getSelectedItemsPos()1768 Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException) 1769 { 1770 if ( m_xAggregateListBox.is() ) 1771 return m_xAggregateListBox->getSelectedItemsPos(); 1772 return Sequence< ::sal_Int16 >( ); 1773 } 1774 1775 //-------------------------------------------------------------------- getSelectedItem()1776 ::rtl::OUString SAL_CALL OListBoxControl::getSelectedItem( ) throw (RuntimeException) 1777 { 1778 if ( m_xAggregateListBox.is() ) 1779 return m_xAggregateListBox->getSelectedItem(); 1780 return ::rtl::OUString( ); 1781 } 1782 1783 //-------------------------------------------------------------------- getSelectedItems()1784 Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getSelectedItems( ) throw (RuntimeException) 1785 { 1786 if ( m_xAggregateListBox.is() ) 1787 return m_xAggregateListBox->getSelectedItems(); 1788 return Sequence< ::rtl::OUString >( ); 1789 } 1790 1791 //-------------------------------------------------------------------- selectItemPos(::sal_Int16 nPos,::sal_Bool bSelect)1792 void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException) 1793 { 1794 if ( m_xAggregateListBox.is() ) 1795 m_xAggregateListBox->selectItemPos( nPos, bSelect ); 1796 } 1797 1798 //-------------------------------------------------------------------- selectItemsPos(const Sequence<::sal_Int16> & aPositions,::sal_Bool bSelect)1799 void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException) 1800 { 1801 if ( m_xAggregateListBox.is() ) 1802 m_xAggregateListBox->selectItemsPos( aPositions, bSelect ); 1803 } 1804 1805 //-------------------------------------------------------------------- selectItem(const::rtl::OUString & aItem,::sal_Bool bSelect)1806 void SAL_CALL OListBoxControl::selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException) 1807 { 1808 if ( m_xAggregateListBox.is() ) 1809 m_xAggregateListBox->selectItem( aItem, bSelect ); 1810 } 1811 1812 //-------------------------------------------------------------------- isMutipleMode()1813 ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode( ) throw (RuntimeException) 1814 { 1815 if ( m_xAggregateListBox.is() ) 1816 return m_xAggregateListBox->isMutipleMode(); 1817 return sal_False; 1818 } 1819 1820 //-------------------------------------------------------------------- setMultipleMode(::sal_Bool bMulti)1821 void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException) 1822 { 1823 if ( m_xAggregateListBox.is() ) 1824 m_xAggregateListBox->setMultipleMode( bMulti ); 1825 } 1826 1827 //-------------------------------------------------------------------- getDropDownLineCount()1828 ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount( ) throw (RuntimeException) 1829 { 1830 if ( m_xAggregateListBox.is() ) 1831 return m_xAggregateListBox->getDropDownLineCount(); 1832 return 0; 1833 } 1834 1835 //-------------------------------------------------------------------- setDropDownLineCount(::sal_Int16 nLines)1836 void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException) 1837 { 1838 if ( m_xAggregateListBox.is() ) 1839 m_xAggregateListBox->setDropDownLineCount( nLines ); 1840 } 1841 1842 //-------------------------------------------------------------------- makeVisible(::sal_Int16 nEntry)1843 void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException) 1844 { 1845 if ( m_xAggregateListBox.is() ) 1846 m_xAggregateListBox->makeVisible( nEntry ); 1847 } 1848 1849 //......................................................................... 1850 } 1851 //......................................................................... 1852 1853