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