bump product version to 4.1.6.2
[LibreOffice.git] / forms / source / component / ListBox.cxx
blobfeedf628afa1ac0008af8f11556224b68290c980
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "ListBox.hxx"
22 #include "property.hxx"
23 #include "property.hrc"
24 #include "services.hxx"
25 #include "frm_resource.hxx"
26 #include "frm_resource.hrc"
27 #include "BaseListBox.hxx"
28 #include "listenercontainers.hxx"
29 #include "componenttools.hxx"
31 #include <com/sun/star/util/XNumberFormatTypes.hpp>
32 #include <com/sun/star/sdbc/XRowSet.hpp>
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
35 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
36 #include <com/sun/star/util/NumberFormat.hpp>
37 #include <com/sun/star/awt/XWindow.hpp>
38 #include <com/sun/star/sdbc/XConnection.hpp>
39 #include <com/sun/star/sdb/CommandType.hpp>
41 #include <comphelper/basicio.hxx>
42 #include <comphelper/container.hxx>
43 #include <comphelper/numbers.hxx>
44 #include <comphelper/listenernotification.hxx>
45 #include <connectivity/dbtools.hxx>
46 #include <connectivity/formattedcolumnvalue.hxx>
47 #include <connectivity/dbconversion.hxx>
48 #include <cppuhelper/queryinterface.hxx>
49 #include <rtl/logfile.hxx>
50 #include <tools/debug.hxx>
51 #include <tools/diagnose_ex.h>
52 #include <unotools/sharedunocomponent.hxx>
53 #include <vcl/svapp.hxx>
55 #include <boost/optional.hpp>
57 #include <algorithm>
58 #include <functional>
59 #include <iterator>
62 //.........................................................................
63 namespace frm
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::sdb;
67 using namespace ::com::sun::star::sdbc;
68 using namespace ::com::sun::star::sdbcx;
69 using namespace ::com::sun::star::beans;
70 using namespace ::com::sun::star::container;
71 using namespace ::com::sun::star::form;
72 using namespace ::com::sun::star::awt;
73 using namespace ::com::sun::star::io;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::util;
76 using namespace ::com::sun::star::form::binding;
77 using namespace ::dbtools;
79 using ::connectivity::ORowSetValue;
81 //==============================================================================
82 //= helper
83 //==============================================================================
84 namespace
86 //--------------------------------------------------------------------------
87 struct RowSetValueToString : public ::std::unary_function< ORowSetValue, OUString >
89 OUString operator()( const ORowSetValue& _value ) const
91 return _value.getString();
95 //--------------------------------------------------------------------------
96 struct AppendRowSetValueString : public ::std::unary_function< OUString, void >
98 AppendRowSetValueString( OUString& _string )
99 :m_string( _string )
103 void operator()( const OUString _append )
105 m_string += _append;
108 private:
109 OUString& m_string;
112 //--------------------------------------------------------------------------
113 Sequence< OUString > lcl_convertToStringSequence( const ValueList& _values )
115 Sequence< OUString > aStrings( _values.size() );
116 ::std::transform(
117 _values.begin(),
118 _values.end(),
119 aStrings.getArray(),
120 RowSetValueToString()
122 return aStrings;
126 //==============================================================================
127 //= ItemEventDescription
128 //==============================================================================
129 typedef ::comphelper::EventHolder< ItemEvent > ItemEventDescription;
131 //==============================================================================
132 //= OListBoxModel
133 //==============================================================================
134 //------------------------------------------------------------------
135 InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
137 return *(new OListBoxModel(_rxFactory));
140 //------------------------------------------------------------------------------
141 Sequence< Type> OListBoxModel::_getTypes()
143 return TypeBag(
144 OBoundControlModel::_getTypes(),
145 OEntryListHelper::getTypes(),
146 OErrorBroadcaster::getTypes()
147 ).getTypes();
150 // stuff common to all constructors
151 void OListBoxModel::init()
153 startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
156 DBG_NAME(OListBoxModel);
157 //------------------------------------------------------------------
158 OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory)
159 :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True )
160 // use the old control name for compatibility reasons
161 ,OEntryListHelper( (OControlModel&)*this )
162 ,OErrorBroadcaster( OComponentHelper::rBHelper )
163 ,m_aListRowSet( getContext() )
164 ,m_nNULLPos(-1)
165 ,m_nBoundColumnType( DataType::SQLNULL )
167 DBG_CTOR(OListBoxModel,NULL);
169 m_nClassId = FormComponentType::LISTBOX;
170 m_eListSourceType = ListSourceType_VALUELIST;
171 m_aBoundColumn <<= (sal_Int16)1;
172 initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ);
174 init();
177 //------------------------------------------------------------------
178 OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
179 :OBoundControlModel( _pOriginal, _rxFactory )
180 ,OEntryListHelper( *_pOriginal, (OControlModel&)*this )
181 ,OErrorBroadcaster( OComponentHelper::rBHelper )
182 ,m_aListRowSet( getContext() )
183 ,m_eListSourceType( _pOriginal->m_eListSourceType )
184 ,m_aBoundColumn( _pOriginal->m_aBoundColumn )
185 ,m_aListSourceValues( _pOriginal->m_aListSourceValues )
186 ,m_aBoundValues( _pOriginal->m_aBoundValues )
187 ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq )
188 ,m_nNULLPos(-1)
189 ,m_nBoundColumnType( DataType::SQLNULL )
191 DBG_CTOR(OListBoxModel,NULL);
193 init();
196 //------------------------------------------------------------------
197 OListBoxModel::~OListBoxModel()
199 if (!OComponentHelper::rBHelper.bDisposed)
201 acquire();
202 dispose();
205 DBG_DTOR(OListBoxModel,NULL);
208 // XCloneable
209 //------------------------------------------------------------------------------
210 IMPLEMENT_DEFAULT_CLONING( OListBoxModel )
212 // XServiceInfo
213 //------------------------------------------------------------------------------
214 StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException)
216 StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
218 sal_Int32 nOldLen = aSupported.getLength();
219 aSupported.realloc( nOldLen + 8 );
220 OUString* pStoreTo = aSupported.getArray() + nOldLen;
222 *pStoreTo++ = BINDABLE_CONTROL_MODEL;
223 *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
224 *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
226 *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
227 *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
229 *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX;
230 *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX;
231 *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX;
233 return aSupported;
236 //------------------------------------------------------------------------------
237 Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException)
239 Any aReturn = OBoundControlModel::queryAggregation( _rType );
240 if ( !aReturn.hasValue() )
241 aReturn = OEntryListHelper::queryInterface( _rType );
242 if ( !aReturn.hasValue() )
243 aReturn = OErrorBroadcaster::queryInterface( _rType );
244 return aReturn;
247 // OComponentHelper
248 //------------------------------------------------------------------------------
249 void OListBoxModel::disposing()
251 OBoundControlModel::disposing();
252 OEntryListHelper::disposing();
253 OErrorBroadcaster::disposing();
256 //------------------------------------------------------------------------------
257 void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
259 switch (_nHandle)
261 case PROPERTY_ID_BOUNDCOLUMN:
262 _rValue <<= m_aBoundColumn;
263 break;
265 case PROPERTY_ID_LISTSOURCETYPE:
266 _rValue <<= m_eListSourceType;
267 break;
269 case PROPERTY_ID_LISTSOURCE:
270 _rValue <<= lcl_convertToStringSequence( m_aListSourceValues );
271 break;
273 case PROPERTY_ID_VALUE_SEQ:
274 _rValue <<= lcl_convertToStringSequence( m_aBoundValues );
275 break;
277 case PROPERTY_ID_SELECT_VALUE_SEQ:
278 _rValue = getCurrentMultiValue();
279 break;
281 case PROPERTY_ID_SELECT_VALUE:
282 _rValue = getCurrentSingleValue();
283 break;
285 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
286 _rValue <<= m_aDefaultSelectSeq;
287 break;
289 case PROPERTY_ID_STRINGITEMLIST:
290 _rValue <<= getStringItemList();
291 break;
293 default:
294 OBoundControlModel::getFastPropertyValue(_rValue, _nHandle);
298 //------------------------------------------------------------------------------
299 void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception)
301 switch (_nHandle)
303 case PROPERTY_ID_BOUNDCOLUMN :
304 DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID),
305 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
306 m_aBoundColumn = _rValue;
307 break;
309 case PROPERTY_ID_LISTSOURCETYPE :
310 DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast<ListSourceType*>(0))),
311 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
312 _rValue >>= m_eListSourceType;
313 break;
315 case PROPERTY_ID_LISTSOURCE:
317 // extract
318 Sequence< OUString > aListSource;
319 OSL_VERIFY( _rValue >>= aListSource );
321 // copy to member
322 ValueList().swap(m_aListSourceValues);
323 ::std::copy(
324 aListSource.getConstArray(),
325 aListSource.getConstArray() + aListSource.getLength(),
326 ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() )
329 // propagate
330 if ( m_eListSourceType == ListSourceType_VALUELIST )
332 setBoundValues(m_aListSourceValues);
334 else
336 if ( m_xCursor.is() && !hasField() && !hasExternalListSource() )
337 // listbox is already connected to a database, and no external list source
338 // data source changed -> refresh
339 loadData( false );
342 break;
344 case PROPERTY_ID_VALUE_SEQ :
345 OSL_FAIL( "ValueItemList is read-only!" );
346 throw PropertyVetoException();
348 case PROPERTY_ID_SELECT_VALUE_SEQ :
350 Sequence< const Any > v;
351 _rValue >>= v;
352 Any newSelectSeq(translateBindingValuesToControlValue(v));
353 setControlValue( newSelectSeq, eOther );
355 break;
357 case PROPERTY_ID_SELECT_VALUE :
359 ORowSetValue v;
360 v.fill(_rValue);
361 Any newSelectSeq(translateDbValueToControlValue(v));
362 setControlValue( newSelectSeq, eOther );
364 break;
366 case PROPERTY_ID_DEFAULT_SELECT_SEQ :
367 DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast< Sequence<sal_Int16>*>(0))),
368 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
369 _rValue >>= m_aDefaultSelectSeq;
371 DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !");
372 if ( m_xAggregateFastSet.is() )
373 setControlValue( _rValue, eOther );
374 break;
376 case PROPERTY_ID_STRINGITEMLIST:
378 ControlModelLock aLock( *this );
379 setNewStringItemList( _rValue, aLock );
380 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
381 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
382 // a lock - so we effectively has two locks here, of which setNewStringItemList can
383 // only control one.
385 resetNoBroadcast();
386 break;
388 default:
389 OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
393 //------------------------------------------------------------------------------
394 sal_Bool OListBoxModel::convertFastPropertyValue(
395 Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
396 throw (IllegalArgumentException)
398 sal_Bool bModified(sal_False);
399 switch (_nHandle)
401 case PROPERTY_ID_BOUNDCOLUMN :
402 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(static_cast<sal_Int16*>(0)));
403 break;
405 case PROPERTY_ID_LISTSOURCETYPE:
406 bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType);
407 break;
409 case PROPERTY_ID_LISTSOURCE:
410 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) );
411 break;
413 case PROPERTY_ID_VALUE_SEQ :
414 OSL_FAIL( "ValueItemList is read-only!" );
415 throw PropertyVetoException();
417 case PROPERTY_ID_SELECT_VALUE_SEQ :
418 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, getCurrentMultiValue());
419 break;
421 case PROPERTY_ID_SELECT_VALUE :
422 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, getCurrentSingleValue());
423 break;
425 case PROPERTY_ID_DEFAULT_SELECT_SEQ :
426 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq);
427 break;
429 case PROPERTY_ID_STRINGITEMLIST:
430 bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue );
431 break;
433 default:
434 return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
436 return bModified;
439 //------------------------------------------------------------------------------
440 void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
442 // if both SelectedItems and StringItemList are set, care for this
443 // #i27024#
444 const Any* pSelectSequenceValue = NULL;
446 const OUString* pStartPos = _rPropertyNames.getConstArray();
447 const OUString* pEndPos = _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
448 const OUString* pSelectedItemsPos = ::std::find_if(
449 pStartPos, pEndPos,
450 ::std::bind2nd( ::std::equal_to< OUString >(), PROPERTY_SELECT_SEQ )
452 const OUString* pStringItemListPos = ::std::find_if(
453 pStartPos, pEndPos,
454 ::std::bind2nd( ::std::equal_to< OUString >(), PROPERTY_STRINGITEMLIST )
456 if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) )
458 // both properties are present
459 // -> remember the value for the select sequence
460 pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos );
463 OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues );
465 if ( pSelectSequenceValue )
467 setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue );
468 // Note that this is the only reliable way, since one of the properties is implemented
469 // by ourself, and one is implemented by the aggregate, we cannot rely on any particular
470 // results when setting them both - too many undocumented behavior in all the involved
475 //------------------------------------------------------------------------------
476 void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const
478 BEGIN_DESCRIBE_PROPERTIES( 9, OBoundControlModel )
479 DECL_PROP1(TABINDEX, sal_Int16, BOUND);
480 DECL_PROP2(BOUNDCOLUMN, sal_Int16, BOUND, MAYBEVOID);
481 DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND);
482 DECL_PROP1(LISTSOURCE, StringSequence, BOUND);
483 DECL_PROP3(VALUE_SEQ, StringSequence, BOUND, READONLY, TRANSIENT);
484 DECL_PROP2(SELECT_VALUE_SEQ, Sequence< Any >, BOUND, TRANSIENT);
485 DECL_PROP2(SELECT_VALUE, Any, BOUND, TRANSIENT);
486 DECL_PROP1(DEFAULT_SELECT_SEQ, Sequence<sal_Int16>, BOUND);
487 DECL_PROP1(STRINGITEMLIST, Sequence< OUString >, BOUND);
488 END_DESCRIBE_PROPERTIES();
491 //------------------------------------------------------------------------------
492 void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException )
494 if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST )
496 ControlModelLock aLock( *this );
497 // SYNCHRONIZED ----->
498 // our aggregate internally changed its StringItemList property - reflect this in our "overridden"
499 // version of the property
500 setNewStringItemList( i_rEvent.NewValue, aLock );
501 // <----- SYNCHRONIZED
502 return;
504 OBoundControlModel::_propertyChanged( i_rEvent );
507 //------------------------------------------------------------------------------
508 void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
510 OBoundControlModel::describeAggregateProperties( _rAggregateProps );
512 // superseded properties:
513 RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST );
516 //------------------------------------------------------------------------------
517 OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException)
519 return OUString(FRM_COMPONENT_LISTBOX); // old (non-sun) name for compatibility !
522 //------------------------------------------------------------------------------
523 void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
524 throw(IOException, RuntimeException)
526 OBoundControlModel::write(_rxOutStream);
528 // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
529 Sequence<sal_Int16> aDummySeq;
531 // Version
532 // Version 0x0002: ListSource becomes StringSeq
533 _rxOutStream->writeShort(0x0004);
535 // Masking for any
536 sal_uInt16 nAnyMask = 0;
537 if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID)
538 nAnyMask |= BOUNDCOLUMN;
540 _rxOutStream << nAnyMask;
542 _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues );
543 _rxOutStream << (sal_Int16)m_eListSourceType;
544 _rxOutStream << aDummySeq;
545 _rxOutStream << m_aDefaultSelectSeq;
547 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
549 sal_Int16 nBoundColumn = 0;
550 m_aBoundColumn >>= nBoundColumn;
551 _rxOutStream << nBoundColumn;
553 writeHelpTextCompatibly(_rxOutStream);
555 // from version 0x0004 : common properties
556 writeCommonProperties(_rxOutStream);
559 //------------------------------------------------------------------------------
560 void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException)
562 // We need to respect dependencies for certain variables.
563 // Therefore, we need to set them explicitly via setPropertyValue().
565 OBoundControlModel::read(_rxInStream);
566 ControlModelLock aLock( *this );
568 // since we are "overwriting" the StringItemList of our aggregate (means we have
569 // an own place to store the value, instead of relying on our aggregate storing it),
570 // we need to respect what the aggregate just read for the StringItemList property.
573 if ( m_xAggregateSet.is() )
574 setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock );
576 catch( const Exception& )
578 OSL_FAIL( "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
581 // Version
582 sal_uInt16 nVersion = _rxInStream->readShort();
583 DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !");
585 if (nVersion > 0x0004)
587 OSL_FAIL("OListBoxModel::read : invalid (means unknown) version !");
588 ValueList().swap(m_aListSourceValues);
589 m_aBoundColumn <<= (sal_Int16)0;
590 clearBoundValues();
591 m_eListSourceType = ListSourceType_VALUELIST;
592 m_aDefaultSelectSeq.realloc(0);
593 defaultCommonProperties();
594 return;
597 // Masking for any
598 sal_uInt16 nAnyMask;
599 _rxInStream >> nAnyMask;
601 // ListSourceSeq
602 StringSequence aListSourceSeq;
603 if (nVersion == 0x0001)
605 // Create ListSourceSeq from String
606 OUString sListSource;
607 _rxInStream >> sListSource;
609 sal_Int32 nTokens = 1;
610 const sal_Unicode* pStr = sListSource.getStr();
611 while ( *pStr )
613 if ( *pStr == ';' )
614 nTokens++;
615 pStr++;
617 aListSourceSeq.realloc( nTokens );
618 for (sal_uInt16 i=0; i<nTokens; ++i)
620 sal_Int32 nTmp = 0;
621 aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp);
624 else
625 _rxInStream >> aListSourceSeq;
627 sal_Int16 nListSourceType;
628 _rxInStream >> nListSourceType;
629 m_eListSourceType = (ListSourceType)nListSourceType;
630 Any aListSourceSeqAny;
631 aListSourceSeqAny <<= aListSourceSeq;
633 setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny );
635 // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
636 Sequence<sal_Int16> aDummySeq;
637 _rxInStream >> aDummySeq;
639 // DefaultSelectSeq
640 Sequence<sal_Int16> aDefaultSelectSeq;
641 _rxInStream >> aDefaultSelectSeq;
642 Any aDefaultSelectSeqAny;
643 aDefaultSelectSeqAny <<= aDefaultSelectSeq;
644 setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny);
646 // BoundColumn
647 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
649 sal_Int16 nValue;
650 _rxInStream >> nValue;
651 m_aBoundColumn <<= nValue;
653 else // the constructor initialises to 1, so if it is empty,
654 // we must explicitly set to empty
656 m_aBoundColumn = Any();
659 if (nVersion > 2)
660 readHelpTextCompatibly(_rxInStream);
662 // if our string list is not filled from the value list, we must empty it
663 // this can be the case when somebody saves in alive mode
664 if ( ( m_eListSourceType != ListSourceType_VALUELIST )
665 && !hasExternalListSource()
668 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
671 if (nVersion > 3)
672 readCommonProperties(_rxInStream);
674 // Display the default values after reading
675 if ( !getControlSource().isEmpty() )
676 // (not if we don't have a control source - the "State" property acts like it is persistent, then
677 resetNoBroadcast();
680 //------------------------------------------------------------------------------
681 void OListBoxModel::loadData( bool _bForce )
683 RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" );
684 DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" );
685 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" );
687 const sal_Int16 nNULLPosBackup( m_nNULLPos );
688 const sal_Int32 nBoundColumnTypeBackup( m_nBoundColumnType );
689 m_nNULLPos = -1;
690 m_nBoundColumnType = DataType::SQLNULL;
692 // pre-requisites:
693 // PRE1: connection
694 Reference< XConnection > xConnection;
695 // is the active connection of our form
696 Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY );
697 if ( xFormProps.is() )
698 xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
700 // PRE2: list source
701 OUString sListSource;
702 // if our list source type is no value list, we need to concatenate
703 // the single list source elements
704 ::std::for_each(
705 m_aListSourceValues.begin(),
706 m_aListSourceValues.end(),
707 AppendRowSetValueString( sListSource )
710 // outta here if we don't have all pre-requisites
711 if ( !xConnection.is() || sListSource.isEmpty() )
713 clearBoundValues();
714 return;
717 ::boost::optional< sal_Int16 > aBoundColumn(0);
718 aBoundColumn.reset();
719 if ( m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT )
721 sal_Int16 nBoundColumn( 0 );
722 m_aBoundColumn >>= nBoundColumn;
723 aBoundColumn.reset( nBoundColumn );
726 ::utl::SharedUNOComponent< XResultSet > xListCursor;
729 m_aListRowSet.setConnection( xConnection );
731 sal_Bool bExecute = sal_False;
732 switch (m_eListSourceType)
734 case ListSourceType_TABLEFIELDS:
735 // don't work with a statement here, the fields will be collected below
736 break;
738 case ListSourceType_TABLE:
740 Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource);
741 Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY);
743 // do we have a bound column if yes we have to select it
744 // and the displayed column is the first column othwhise we act as a combobox
745 OUString aFieldName;
746 OUString aBoundFieldName;
748 if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && xFieldsByIndex.is() )
750 if ( *aBoundColumn >= xFieldsByIndex->getCount() )
751 break;
753 Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex( *aBoundColumn ),UNO_QUERY);
754 assert(xFieldAsSet.is());
755 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName;
756 aBoundColumn.reset( 1 );
758 xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY);
759 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName;
761 else if (xFieldsByName.is())
763 if ( xFieldsByName->hasByName( getControlSource() ) )
764 aFieldName = getControlSource();
765 else
767 // otherwise look for the alias
768 Reference< XColumnsSupplier > xSupplyFields;
769 xFormProps->getPropertyValue(OUString("SingleSelectQueryComposer")) >>= xSupplyFields;
771 // search the field
772 DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !");
774 Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns();
775 if ( xFieldNames->hasByName( getControlSource() ) )
777 Reference<XPropertySet> xComposerFieldAsSet;
778 xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet;
779 if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet))
780 xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName;
784 if (aFieldName.isEmpty())
785 break;
787 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
788 OUString aQuote = xMeta->getIdentifierQuoteString();
789 OUString aStatement("SELECT ");
790 if (aBoundFieldName.isEmpty()) // act like a combobox
791 aStatement += OUString("DISTINCT ");
793 aStatement += quoteName(aQuote,aFieldName);
794 if (!aBoundFieldName.isEmpty())
796 aStatement += OUString(", ");
797 aStatement += quoteName(aQuote, aBoundFieldName);
799 aStatement += OUString(" FROM ");
801 OUString sCatalog, sSchema, sTable;
802 qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation );
803 aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable );
805 m_aListRowSet.setEscapeProcessing( sal_False );
806 m_aListRowSet.setCommand( aStatement );
807 bExecute = sal_True;
809 break;
811 case ListSourceType_QUERY:
812 m_aListRowSet.setCommandFromQuery( sListSource );
813 bExecute = sal_True;
814 break;
816 default:
817 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType );
818 m_aListRowSet.setCommand( sListSource );
819 bExecute = sal_True;
820 break;
823 if (bExecute)
825 if ( !_bForce && !m_aListRowSet.isDirty() )
827 // if none of the settings of the row set changed, compared to the last
828 // invocation of loadData, then don't re-fill the list. Instead, assume
829 // the list entries are the same.
830 m_nNULLPos = nNULLPosBackup;
831 m_nBoundColumnType = nBoundColumnTypeBackup;
832 return;
834 xListCursor.reset( m_aListRowSet.execute() );
837 catch(const SQLException& eSQL)
839 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
840 return;
842 catch(const Exception& eUnknown)
844 (void)eUnknown;
845 return;
848 // Fill display and value lists
849 ValueList aDisplayList, aValueList;
850 sal_Bool bUseNULL = hasField() && !isRequired();
852 // empty BoundColumn is treated as BoundColumn=0,
853 if(!aBoundColumn)
854 aBoundColumn = 0;
858 OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ),
859 "OListBoxModel::loadData: logic error!" );
860 if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) )
861 return;
863 switch (m_eListSourceType)
865 case ListSourceType_SQL:
866 case ListSourceType_SQLPASSTHROUGH:
867 case ListSourceType_TABLE:
868 case ListSourceType_QUERY:
870 // Get field of the ResultSet's 1st column
871 Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY);
872 DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
873 Reference<XIndexAccess> xColumns;
874 if (xSupplyCols.is())
876 xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
877 DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !");
880 Reference< XPropertySet > xDataField;
881 if ( xColumns.is() )
882 xColumns->getByIndex(0) >>= xDataField;
883 if ( !xDataField.is() )
884 return;
886 ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField );
888 // Get the field of BoundColumn of the ResultSet
889 m_nBoundColumnType = DataType::SQLNULL;
890 if ( *aBoundColumn >= 0 )
894 Reference< XPropertySet > xBoundField( xColumns->getByIndex( *aBoundColumn ), UNO_QUERY_THROW );
895 OSL_VERIFY( xBoundField->getPropertyValue( OUString("Type") ) >>= m_nBoundColumnType );
897 catch( const Exception& )
899 DBG_UNHANDLED_EXCEPTION();
902 else if ( *aBoundColumn == -1)
903 m_nBoundColumnType = DataType::SMALLINT;
905 // If the LB is bound to a field and empty entries are valid, we remember the position
906 // for an empty entry
907 RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" );
908 OUString aStr;
909 sal_Int16 entryPos = 0;
910 ORowSetValue aBoundValue;
911 Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW );
912 while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries
914 aStr = aValueFormatter.getFormattedValue();
915 aDisplayList.push_back( aStr );
917 if(*aBoundColumn >= 0)
918 aBoundValue.fill( *aBoundColumn + 1, m_nBoundColumnType, xCursorRow );
919 else
920 // -1 because getRow() is 1-indexed, but ListBox positions are 0-indexed
921 aBoundValue = static_cast<sal_Int16>(xListCursor->getRow()-1);
922 aValueList.push_back( aBoundValue );
924 if ( m_nNULLPos == -1 && aBoundValue.isNull() )
925 m_nNULLPos = sal_Int16( aDisplayList.size() - 1 );
926 if ( bUseNULL && ( m_nNULLPos == -1 ) && aStr.isEmpty() )
927 // There is already a non-NULL entry with empty display string;
928 // adding another one for NULL would make things confusing,
929 // so back off.
930 bUseNULL = false;
933 break;
935 case ListSourceType_TABLEFIELDS:
937 Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource);
938 if (xFieldNames.is())
940 StringSequence seqNames = xFieldNames->getElementNames();
941 ::std::copy(
942 seqNames.getConstArray(),
943 seqNames.getConstArray() + seqNames.getLength(),
944 ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() )
946 if(*aBoundColumn == -1)
948 // the type of i matters! It will be the type of the ORowSetValue pushed to aValueList!
949 for(sal_Int16 i=0; static_cast<ValueList::size_type>(i) < aDisplayList.size(); ++i)
951 aValueList.push_back(i);
954 else
956 aValueList = aDisplayList;
960 break;
961 default:
962 OSL_FAIL( "OListBoxModel::loadData: unreachable!" );
963 break;
966 catch(const SQLException& eSQL)
968 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
969 return;
971 catch( const Exception& )
973 DBG_UNHANDLED_EXCEPTION();
974 return;
978 // Create Values sequence
979 // Add NULL entry
980 if (bUseNULL && m_nNULLPos == -1)
982 aValueList.insert( aValueList.begin(), ORowSetValue() );
984 aDisplayList.insert( aDisplayList.begin(), ORowSetValue( OUString() ) );
985 m_nNULLPos = 0;
988 setBoundValues(aValueList);
990 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) );
993 //------------------------------------------------------------------------------
994 void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
996 // list boxes which are bound to a db column don't have multi selection
997 // - this would be unable to reflect in the db column
998 if ( hasField() )
1000 setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) );
1003 if ( !hasExternalListSource() )
1004 impl_refreshDbEntryList( false );
1007 //------------------------------------------------------------------------------
1008 void OListBoxModel::onDisconnectedDbColumn()
1010 if ( m_eListSourceType != ListSourceType_VALUELIST )
1012 clearBoundValues();
1013 m_nNULLPos = -1;
1014 m_nBoundColumnType = DataType::SQLNULL;
1016 if ( !hasExternalListSource() )
1017 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
1019 m_aListRowSet.dispose();
1023 //------------------------------------------------------------------------------
1024 void OListBoxModel::setBoundValues(const ValueList &l)
1026 m_aConvertedBoundValues.clear();
1027 m_aBoundValues = l;
1030 //------------------------------------------------------------------------------
1031 void OListBoxModel::clearBoundValues()
1033 ValueList().swap(m_aConvertedBoundValues);
1034 ValueList().swap(m_aBoundValues);
1037 //------------------------------------------------------------------------------
1038 void OListBoxModel::convertBoundValues(const sal_Int32 nFieldType) const
1040 m_aConvertedBoundValues.resize(m_aBoundValues.size());
1041 ValueList::const_iterator src = m_aBoundValues.begin();
1042 const ValueList::const_iterator end = m_aBoundValues.end();
1043 ValueList::iterator dst = m_aConvertedBoundValues.begin();
1044 for (; src != end; ++src, ++dst )
1046 *dst = *src;
1047 dst->setTypeKind(nFieldType);
1049 m_nConvertedBoundValuesType = nFieldType;
1050 OSL_ENSURE(dst == m_aConvertedBoundValues.end(), "OListBoxModel::convertBoundValues expected to have overwritten all of m_aConvertedBoundValues, but did not.");
1051 assert(dst == m_aConvertedBoundValues.end());
1053 //------------------------------------------------------------------------------
1054 sal_Int32 OListBoxModel::getValueType() const
1056 return impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType();
1058 //------------------------------------------------------------------------------
1059 ValueList OListBoxModel::impl_getValues() const
1061 const sal_Int32 nFieldType = getValueType();
1063 if ( !m_aConvertedBoundValues.empty() && m_nConvertedBoundValuesType == nFieldType )
1064 return m_aConvertedBoundValues;
1066 if ( !m_aBoundValues.empty() )
1068 convertBoundValues(nFieldType);
1069 return m_aConvertedBoundValues;
1072 Sequence< OUString > aStringItems( getStringItemList() );
1073 ValueList aValues( aStringItems.getLength() );
1074 ValueList::iterator dst = aValues.begin();
1075 const OUString *src (aStringItems.getConstArray());
1076 const OUString * const end = src + aStringItems.getLength();
1077 for (; src < end; ++src, ++dst )
1079 *dst = *src;
1080 dst->setTypeKind(nFieldType);
1082 m_nConvertedBoundValuesType = nFieldType;
1083 OSL_ENSURE(dst == aValues.end(), "OListBoxModel::impl_getValues expected to have set all of aValues, but did not.");
1084 assert(dst == aValues.end());
1085 return aValues;
1087 //------------------------------------------------------------------------------
1088 ORowSetValue OListBoxModel::getFirstSelectedValue() const
1090 static const ORowSetValue s_aEmptyVaue;
1092 DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" );
1093 if ( !m_xAggregateFastSet.is() )
1094 return s_aEmptyVaue;
1096 Sequence< sal_Int16 > aSelectedIndices;
1097 OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices );
1098 if ( !aSelectedIndices.getLength() )
1099 // nothing selected at all
1100 return s_aEmptyVaue;
1102 if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) )
1103 // the dedicated "NULL" entry is selected
1104 return s_aEmptyVaue;
1106 ValueList aValues( impl_getValues() );
1108 size_t selectedValue = aSelectedIndices[0];
1109 if ( selectedValue >= aValues.size() )
1111 OSL_FAIL( "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" );
1112 return s_aEmptyVaue;
1115 return aValues[ selectedValue ];
1118 //------------------------------------------------------------------------------
1119 sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1121 // current selection list
1122 const ORowSetValue aCurrentValue( getFirstSelectedValue() );
1123 if ( aCurrentValue != m_aSaveValue )
1125 if ( aCurrentValue.isNull() )
1126 m_xColumnUpdate->updateNull();
1127 else
1131 m_xColumnUpdate->updateObject( aCurrentValue.makeAny() );
1133 catch ( const Exception& )
1135 return sal_False;
1138 m_aSaveValue = aCurrentValue;
1140 return sal_True;
1143 //------------------------------------------------------------------------------
1144 Sequence< sal_Int16 > OListBoxModel::translateDbValueToControlValue(const ORowSetValue &i_aValue) const
1146 Sequence< sal_Int16 > aSelectionIndicies;
1148 // reset selection for NULL values
1149 if ( i_aValue.isNull() )
1151 if ( m_nNULLPos != -1 )
1153 aSelectionIndicies.realloc(1);
1154 aSelectionIndicies[0] = m_nNULLPos;
1157 else
1159 ValueList aValues( impl_getValues() );
1160 assert( m_nConvertedBoundValuesType == getValueType());
1161 ORowSetValue v(i_aValue);
1162 v.setTypeKind( m_nConvertedBoundValuesType );
1163 ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), v );
1164 if ( curValuePos != aValues.end() )
1166 aSelectionIndicies.realloc( 1 );
1167 aSelectionIndicies[0] = curValuePos - aValues.begin();
1171 return aSelectionIndicies;
1173 //------------------------------------------------------------------------------
1174 Sequence< sal_Int16 > OListBoxModel::translateBindingValuesToControlValue(const Sequence< const Any > &i_aValues) const
1176 const ValueList aValues( impl_getValues() );
1177 assert( m_nConvertedBoundValuesType == getValueType());
1178 Sequence< sal_Int16 > aSelectionIndicies(i_aValues.getLength());
1179 sal_Int32 nCount(0);
1181 sal_Int16 *pIndex = aSelectionIndicies.getArray();
1182 const Any *pValue = i_aValues.getConstArray();
1183 const Any * const pValueEnd = i_aValues.getConstArray() + i_aValues.getLength();
1184 for (;pValue < pValueEnd; ++pValue)
1186 if ( pValue->hasValue() )
1188 ORowSetValue v;
1189 v.fill(*pValue);
1190 v.setTypeKind( m_nConvertedBoundValuesType );
1191 ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), v );
1192 if ( curValuePos != aValues.end() )
1194 *pIndex = curValuePos - aValues.begin();
1195 ++pIndex;
1196 ++nCount;
1199 else
1201 if ( m_nNULLPos != -1 )
1203 *pIndex = m_nNULLPos;
1204 ++pIndex;
1205 ++nCount;
1209 assert(aSelectionIndicies.getArray() + nCount == pIndex);
1210 aSelectionIndicies.realloc(nCount);
1211 return aSelectionIndicies;
1213 //------------------------------------------------------------------------------
1214 Any OListBoxModel::translateDbColumnToControlValue()
1216 Reference< XPropertySet > xBoundField( getField() );
1217 if ( !xBoundField.is() )
1219 OSL_FAIL( "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" );
1220 return Any();
1223 ORowSetValue aCurrentValue;
1224 aCurrentValue.fill( getValueType(), m_xColumn );
1226 m_aSaveValue = aCurrentValue;
1228 return makeAny( translateDbValueToControlValue(aCurrentValue) );
1231 // XReset
1232 //------------------------------------------------------------------------------
1233 Any OListBoxModel::getDefaultForReset() const
1235 Any aValue;
1236 if (m_aDefaultSelectSeq.getLength())
1237 aValue <<= m_aDefaultSelectSeq;
1238 else if (m_nNULLPos != -1) // bound Listbox
1240 Sequence<sal_Int16> aSeq(1);
1241 aSeq.getArray()[0] = m_nNULLPos;
1242 aValue <<= aSeq;
1244 else
1246 Sequence<sal_Int16> aSeq;
1247 aValue <<= aSeq;
1250 return aValue;
1253 //--------------------------------------------------------------------
1254 void OListBoxModel::resetNoBroadcast()
1256 OBoundControlModel::resetNoBroadcast();
1257 m_aSaveValue.setNull();
1260 //--------------------------------------------------------------------
1261 void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException )
1263 if ( !OEntryListHelper::handleDisposing( _rSource ) )
1264 OBoundControlModel::disposing( _rSource );
1267 //--------------------------------------------------------------------
1268 namespace
1270 // The type of how we should transfer our selection to external value bindings
1271 enum ExchangeType
1273 eIndexList, /// as list of indexes of selected entries
1274 eIndex, /// as index of the selected entry
1275 eEntryList, /// as list of string representations of selected *display* entries
1276 eEntry, /// as string representation of the selected *display* entry
1277 eValueList, /// as list of string representations of selected values
1278 eValue /// as string representation of the selected value
1281 //--------------------------------------------------------------------
1282 ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType )
1284 switch ( _rExchangeType.getTypeClass() )
1286 case TypeClass_ANY:
1287 return eValue;
1288 case TypeClass_STRING:
1289 return eEntry;
1290 case TypeClass_LONG:
1291 return eIndex;
1292 case TypeClass_SEQUENCE:
1294 Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType );
1295 switch ( aElementType.getTypeClass() )
1297 case TypeClass_ANY:
1298 return eValueList;
1299 case TypeClass_STRING:
1300 return eEntryList;
1301 case TypeClass_LONG:
1302 return eIndexList;
1303 default:
1304 break;
1307 default:
1308 break;
1310 OSL_FAIL( "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" );
1311 return eEntry;
1315 //--------------------------------------------------------------------
1316 Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1318 Sequence< sal_Int16 > aSelectIndexes;
1320 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1322 case eValueList:
1324 Sequence< const Any > aExternalValues;
1325 OSL_VERIFY( _rExternalValue >>= aExternalValues );
1326 aSelectIndexes = translateBindingValuesToControlValue( aExternalValues );
1328 break;
1330 case eValue:
1332 ORowSetValue v;
1333 v.fill(_rExternalValue);
1334 aSelectIndexes = translateDbValueToControlValue(v);
1336 break;
1338 case eIndexList:
1340 // unfortunately, our select sequence is a sequence<short>, while the external binding
1341 // supplies sequence<int> only -> transform this
1342 Sequence< sal_Int32 > aSelectIndexesPure;
1343 OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure );
1344 aSelectIndexes.realloc( aSelectIndexesPure.getLength() );
1345 ::std::copy(
1346 aSelectIndexesPure.getConstArray(),
1347 aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(),
1348 aSelectIndexes.getArray()
1351 break;
1353 case eIndex:
1355 sal_Int32 nSelectIndex = -1;
1356 OSL_VERIFY( _rExternalValue >>= nSelectIndex );
1357 if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) )
1359 aSelectIndexes.realloc( 1 );
1360 aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex );
1363 break;
1365 case eEntryList:
1367 // we can retrieve a string list from the binding for multiple selection
1368 Sequence< OUString > aSelectEntries;
1369 OSL_VERIFY( _rExternalValue >>= aSelectEntries );
1371 ::std::set< sal_Int16 > aSelectionSet;
1373 // find the selection entries in our item list
1374 const OUString* pSelectEntries = aSelectEntries.getArray();
1375 const OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength();
1376 while ( pSelectEntries != pSelectEntriesEnd )
1378 // the indexes where the current string appears in our string items
1379 Sequence< sal_Int16 > aThisEntryIndexes;
1380 aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False );
1382 // insert all the indexes of this entry into our set
1383 ::std::copy(
1384 aThisEntryIndexes.getConstArray(),
1385 aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(),
1386 ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() )
1390 // copy the indexes to the sequence
1391 aSelectIndexes.realloc( aSelectionSet.size() );
1392 ::std::copy(
1393 aSelectionSet.begin(),
1394 aSelectionSet.end(),
1395 aSelectIndexes.getArray()
1398 break;
1400 case eEntry:
1402 OUString sStringToSelect;
1403 OSL_VERIFY( _rExternalValue >>= sStringToSelect );
1405 aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False );
1407 break;
1410 return makeAny( aSelectIndexes );
1413 //--------------------------------------------------------------------
1414 namespace
1416 //................................................................
1417 struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, OUString >
1419 protected:
1420 const Sequence< OUString >& m_rList;
1422 public:
1423 ExtractStringFromSequence_Safe( const Sequence< OUString >& _rList ) : m_rList( _rList ) { }
1425 OUString operator ()( sal_Int16 _nIndex )
1427 OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" );
1428 if ( _nIndex < m_rList.getLength() )
1429 return m_rList[ _nIndex ];
1430 return OUString();
1434 //................................................................
1435 Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< OUString >& _rStringList )
1437 Any aReturn;
1439 // by definition, multiple selected entries are transferred as NULL if the
1440 // binding does not support string lists
1441 if ( _rSelectSequence.getLength() <= 1 )
1443 OUString sSelectedEntry;
1445 if ( _rSelectSequence.getLength() == 1 )
1446 sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] );
1448 aReturn <<= sSelectedEntry;
1451 return aReturn;
1454 //................................................................
1455 Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< OUString >& _rStringList )
1457 Sequence< OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() );
1458 ::std::transform(
1459 _rSelectSequence.getConstArray(),
1460 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
1461 aSelectedEntriesTexts.getArray(),
1462 ExtractStringFromSequence_Safe( _rStringList )
1464 return makeAny( aSelectedEntriesTexts );
1467 //................................................................
1468 struct ExtractAnyFromValueList_Safe : public ::std::unary_function< sal_Int16, Any >
1470 protected:
1471 const ValueList& m_rList;
1473 public:
1474 ExtractAnyFromValueList_Safe( const ValueList& _rList ) : m_rList( _rList ) { }
1476 Any operator ()( sal_Int16 _nIndex )
1478 OSL_ENSURE( static_cast<ValueList::size_type>(_nIndex) < m_rList.size(), "ExtractAnyFromValueList: inconsistence!" );
1479 if ( static_cast<ValueList::size_type>(_nIndex) < m_rList.size() )
1480 return m_rList[ _nIndex ].makeAny();
1481 return Any();
1485 //................................................................
1486 Any lcl_getSingleSelectedEntryAny( const Sequence< sal_Int16 >& _rSelectSequence, const ValueList& _rStringList )
1488 Any aReturn;
1490 // by definition, multiple selected entries are transfered as NULL if the
1491 // binding does not support string lists
1492 if ( _rSelectSequence.getLength() <= 1 )
1494 if ( _rSelectSequence.getLength() == 1 )
1495 aReturn = ExtractAnyFromValueList_Safe( _rStringList )( _rSelectSequence[0] );
1498 return aReturn;
1501 //................................................................
1502 Any lcl_getMultiSelectedEntriesAny( const Sequence< sal_Int16 >& _rSelectSequence, const ValueList& _rStringList )
1504 Sequence< Any > aSelectedEntriesValues( _rSelectSequence.getLength() );
1505 ::std::transform(
1506 _rSelectSequence.getConstArray(),
1507 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
1508 aSelectedEntriesValues.getArray(),
1509 ExtractAnyFromValueList_Safe( _rStringList )
1511 return makeAny( aSelectedEntriesValues );
1515 //--------------------------------------------------------------------
1516 Any OListBoxModel::translateControlValueToExternalValue( ) const
1518 OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" );
1520 Sequence< sal_Int16 > aSelectSequence;
1521 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1523 Any aReturn;
1524 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1526 case eValueList:
1527 aReturn = getCurrentMultiValue();
1528 break;
1530 case eValue:
1531 aReturn = getCurrentSingleValue();
1532 break;
1534 case eIndexList:
1536 // unfortunately, the select sequence is a sequence<short>, but our binding
1537 // expects int's
1538 Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() );
1539 ::std::copy(
1540 aSelectSequence.getConstArray(),
1541 aSelectSequence.getConstArray() + aSelectSequence.getLength(),
1542 aTransformed.getArray()
1544 aReturn <<= aTransformed;
1546 break;
1548 case eIndex:
1549 if ( aSelectSequence.getLength() <= 1 )
1551 sal_Int32 nIndex = -1;
1553 if ( aSelectSequence.getLength() == 1 )
1554 nIndex = aSelectSequence[0];
1556 aReturn <<= nIndex;
1558 break;
1560 case eEntryList:
1561 aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
1562 break;
1564 case eEntry:
1565 aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
1566 break;
1569 return aReturn;
1572 //------------------------------------------------------------------------------
1573 Any OListBoxModel::translateControlValueToValidatableValue( ) const
1575 OSL_PRECOND( hasValidator(), "OListBoxModel::translateControlValueToValidatableValue: no validator, so why should I?" );
1576 return getCurrentFormComponentValue();
1579 //--------------------------------------------------------------------
1580 Any OListBoxModel::getCurrentSingleValue() const
1582 Any aCurrentValue;
1586 Sequence< sal_Int16 > aSelectSequence;
1587 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1588 aCurrentValue = lcl_getSingleSelectedEntryAny( aSelectSequence, impl_getValues() );
1590 catch( const Exception& )
1592 DBG_UNHANDLED_EXCEPTION();
1595 return aCurrentValue;
1597 //--------------------------------------------------------------------
1598 Any OListBoxModel::getCurrentMultiValue() const
1600 Any aCurrentValue;
1604 Sequence< sal_Int16 > aSelectSequence;
1605 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1606 aCurrentValue = lcl_getMultiSelectedEntriesAny( aSelectSequence, impl_getValues() );
1608 catch( const Exception& )
1610 DBG_UNHANDLED_EXCEPTION();
1613 return aCurrentValue;
1615 //--------------------------------------------------------------------
1616 Any OListBoxModel::getCurrentFormComponentValue() const
1619 Reference< com::sun::star::form::validation::XValidator > vtor (const_cast<OListBoxModel*>(this)->getValidator());
1620 Reference< XValueBinding > extBinding (const_cast<OListBoxModel*>(this)->getValueBinding());
1621 if ( vtor.is() && vtor == extBinding )
1622 return translateControlValueToExternalValue();
1625 Any aCurrentValue;
1629 sal_Bool bMultiSelection( sal_False );
1630 OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection );
1632 if ( bMultiSelection )
1633 aCurrentValue = getCurrentMultiValue();
1634 else
1635 aCurrentValue = getCurrentSingleValue();
1637 catch( const Exception& )
1639 DBG_UNHANDLED_EXCEPTION();
1642 return aCurrentValue;
1645 //--------------------------------------------------------------------
1646 Sequence< Type > OListBoxModel::getSupportedBindingTypes()
1648 Sequence< Type > aTypes(6);
1649 aTypes[0] = ::getCppuType( static_cast< Sequence< Any >* >( NULL ) );
1650 aTypes[1] = ::getCppuType( static_cast< Any* >( NULL ) );
1651 aTypes[2] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) );
1652 aTypes[3] = ::getCppuType( static_cast< sal_Int32* >( NULL ) );
1653 aTypes[4] = ::getCppuType( static_cast< Sequence< OUString >* >( NULL ) );
1654 aTypes[5] = ::getCppuType( static_cast< OUString* >( NULL ) );
1655 return aTypes;
1658 //--------------------------------------------------------------------
1659 void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock )
1661 if ( !m_xAggregateSet.is() )
1662 return;
1664 suspendValueListening();
1667 m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) );
1669 catch( const Exception& )
1671 DBG_UNHANDLED_EXCEPTION();
1673 resumeValueListening();
1675 // update the selection here
1676 if ( hasExternalValueBinding( ) )
1677 transferExternalValueToControl( _rInstanceLock );
1678 else
1680 if ( hasField() )
1682 // TODO: update the selection in case we're bound to a database column
1684 else
1686 if ( m_aDefaultSelectSeq.getLength() )
1687 setControlValue( makeAny( m_aDefaultSelectSeq ), eOther );
1692 //--------------------------------------------------------------------
1693 void OListBoxModel::connectedExternalListSource( )
1695 // TODO?
1698 //--------------------------------------------------------------------
1699 void OListBoxModel::disconnectedExternalListSource( )
1701 // TODO: in case we're part of an already loaded form, we should probably simulate
1702 // an onConnectedDbColumn, so our list get's filled with the data as indicated
1703 // by our SQL-binding related properties
1706 //--------------------------------------------------------------------
1707 void OListBoxModel::impl_refreshDbEntryList( bool _bForce )
1709 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" );
1711 if ( !hasExternalListSource( )
1712 && ( m_eListSourceType != ListSourceType_VALUELIST )
1713 && ( m_xCursor.is() )
1716 loadData( _bForce );
1720 //--------------------------------------------------------------------
1721 void OListBoxModel::refreshInternalEntryList()
1723 impl_refreshDbEntryList( true );
1724 if ( hasField() && m_xCursor.is() )
1725 initFromField( m_xCursor );
1728 //==================================================================
1729 // OListBoxControl
1730 //==================================================================
1732 //------------------------------------------------------------------
1733 InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
1735 return *(new OListBoxControl(_rxFactory));
1738 //------------------------------------------------------------------------------
1739 Sequence< Type> OListBoxControl::_getTypes()
1741 return TypeBag(
1742 OBoundControl::_getTypes(),
1743 OListBoxControl_BASE::getTypes()
1744 ).getTypes();
1747 //------------------------------------------------------------------
1748 Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException)
1750 Any aReturn = OListBoxControl_BASE::queryInterface( _rType );
1752 if ( !aReturn.hasValue()
1753 || _rType.equals( XTypeProvider::static_type() )
1755 aReturn = OBoundControl::queryAggregation( _rType );
1757 return aReturn;
1760 DBG_NAME(OListBoxControl);
1761 //------------------------------------------------------------------------------
1762 OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory)
1763 :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False )
1764 ,m_aChangeListeners( m_aMutex )
1765 ,m_aItemListeners( m_aMutex )
1767 DBG_CTOR(OListBoxControl,NULL);
1769 increment(m_refCount);
1771 // Register as FocusListener
1772 Reference<XWindow> xComp;
1773 if (query_aggregation(m_xAggregate, xComp))
1774 xComp->addFocusListener(this);
1776 // Register as ItemListener
1777 if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) )
1778 m_xAggregateListBox->addItemListener(this);
1780 // Refcount at 2 for registered Listener
1781 decrement(m_refCount);
1783 doSetDelegator();
1785 m_aChangeTimer.SetTimeout(500);
1786 m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout));
1789 //------------------------------------------------------------------------------
1790 OListBoxControl::~OListBoxControl()
1792 if (!OComponentHelper::rBHelper.bDisposed)
1794 acquire();
1795 dispose();
1798 doResetDelegator();
1799 m_xAggregateListBox.clear();
1801 DBG_DTOR(OListBoxControl,NULL);
1804 //------------------------------------------------------------------------------
1805 StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException)
1807 StringSequence aSupported = OBoundControl::getSupportedServiceNames();
1808 aSupported.realloc(aSupported.getLength() + 1);
1810 OUString* pArray = aSupported.getArray();
1811 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX;
1812 return aSupported;
1816 // XFocusListener
1817 //------------------------------------------------------------------------------
1818 void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
1820 ::osl::MutexGuard aGuard(m_aMutex);
1821 if ( m_aChangeListeners.getLength() ) // only if there are listeners
1823 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1824 if (xSet.is())
1826 // memorize the current selection for posting the change event
1827 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1832 //------------------------------------------------------------------------------
1833 void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
1835 m_aCurrentSelection.clear();
1838 // XItemListener
1839 //------------------------------------------------------------------------------
1840 void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException)
1842 // forward this to our listeners
1843 Reference< XChild > xChild( getModel(), UNO_QUERY );
1844 if ( xChild.is() && xChild->getParent().is() )
1846 ::osl::MutexGuard aGuard( m_aMutex );
1847 if ( m_aItemListeners.getLength() )
1849 if ( !m_pItemBroadcaster.is() )
1851 m_pItemBroadcaster.set(
1852 new ::comphelper::AsyncEventNotifier("ListBox"));
1853 m_pItemBroadcaster->launch();
1855 m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this );
1858 else
1859 m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, _rEvent );
1861 // and do the handling for the ChangeListeners
1862 ::osl::ClearableMutexGuard aGuard(m_aMutex);
1863 if ( m_aChangeTimer.IsActive() )
1865 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1866 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1868 m_aChangeTimer.Stop();
1869 m_aChangeTimer.Start();
1871 else
1873 if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() )
1875 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1876 if (xSet.is())
1878 // Has the selection been changed?
1879 sal_Bool bModified(sal_False);
1880 Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1882 Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue();
1883 Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue();
1884 sal_Int32 nLen = rSelection.getLength();
1885 if (nLen != rOldSelection.getLength())
1886 bModified = sal_True;
1887 else
1889 const sal_Int16* pVal = rSelection.getConstArray();
1890 const sal_Int16* pCompVal = rOldSelection.getConstArray();
1892 while (nLen-- && !bModified)
1893 bModified = pVal[nLen] != pCompVal[nLen];
1896 if (bModified)
1898 m_aCurrentSelection = aValue;
1899 m_aChangeTimer.Start();
1903 else if (m_aCurrentSelection.hasValue())
1904 m_aCurrentSelection.clear();
1908 // XEventListener
1909 //------------------------------------------------------------------------------
1910 void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException)
1912 OBoundControl::disposing(_rSource);
1915 // XChangeBroadcaster
1916 //------------------------------------------------------------------------------
1917 void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
1919 m_aChangeListeners.addInterface( _rxListener );
1922 //------------------------------------------------------------------------------
1923 void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
1925 m_aChangeListeners.removeInterface( _rxListener );
1928 // OComponentHelper
1929 //------------------------------------------------------------------------------
1930 void OListBoxControl::disposing()
1932 if (m_aChangeTimer.IsActive())
1933 m_aChangeTimer.Stop();
1935 EventObject aEvent( *this );
1936 m_aChangeListeners.disposeAndClear( aEvent );
1937 m_aItemListeners.disposeAndClear( aEvent );
1939 rtl::Reference< comphelper::AsyncEventNotifier > t;
1941 ::osl::MutexGuard aGuard( m_aMutex );
1942 if ( m_pItemBroadcaster.is() )
1944 t = m_pItemBroadcaster;
1945 m_pItemBroadcaster->removeEventsForProcessor( this );
1946 m_pItemBroadcaster->terminate();
1947 m_pItemBroadcaster = NULL;
1950 if (t.is()) {
1951 t->join();
1954 OBoundControl::disposing();
1957 //------------------------------------------------------------------------------
1958 void OListBoxControl::processEvent( const AnyEvent& _rEvent )
1960 Reference< XListBox > xKeepAlive( this );
1962 ::osl::MutexGuard aGuard( m_aMutex );
1963 if ( OComponentHelper::rBHelper.bDisposed )
1964 return;
1966 const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent );
1967 m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() );
1970 //------------------------------------------------------------------------------
1971 IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/)
1973 m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) );
1974 return 0L;
1977 //--------------------------------------------------------------------
1978 void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
1980 m_aItemListeners.addInterface( l );
1983 //--------------------------------------------------------------------
1984 void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
1986 m_aItemListeners.removeInterface( l );
1989 //--------------------------------------------------------------------
1990 void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
1992 if ( m_xAggregateListBox.is() )
1993 m_xAggregateListBox->addActionListener( l );
1996 //--------------------------------------------------------------------
1997 void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
1999 if ( m_xAggregateListBox.is() )
2000 m_xAggregateListBox->removeActionListener( l );
2003 //--------------------------------------------------------------------
2004 void SAL_CALL OListBoxControl::addItem( const OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException)
2006 if ( m_xAggregateListBox.is() )
2007 m_xAggregateListBox->addItem( aItem, nPos );
2010 //--------------------------------------------------------------------
2011 void SAL_CALL OListBoxControl::addItems( const Sequence< OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException)
2013 if ( m_xAggregateListBox.is() )
2014 m_xAggregateListBox->addItems( aItems, nPos );
2017 //--------------------------------------------------------------------
2018 void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException)
2020 if ( m_xAggregateListBox.is() )
2021 m_xAggregateListBox->removeItems( nPos, nCount );
2024 //--------------------------------------------------------------------
2025 ::sal_Int16 SAL_CALL OListBoxControl::getItemCount( ) throw (RuntimeException)
2027 if ( m_xAggregateListBox.is() )
2028 return m_xAggregateListBox->getItemCount();
2029 return 0;
2032 //--------------------------------------------------------------------
2033 OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException)
2035 if ( m_xAggregateListBox.is() )
2036 return m_xAggregateListBox->getItem( nPos );
2037 return OUString( );
2040 //--------------------------------------------------------------------
2041 Sequence< OUString > SAL_CALL OListBoxControl::getItems( ) throw (RuntimeException)
2043 if ( m_xAggregateListBox.is() )
2044 return m_xAggregateListBox->getItems();
2045 return Sequence< OUString >( );
2048 //--------------------------------------------------------------------
2049 ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos( ) throw (RuntimeException)
2051 if ( m_xAggregateListBox.is() )
2052 return m_xAggregateListBox->getSelectedItemPos();
2053 return 0;
2056 //--------------------------------------------------------------------
2057 Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException)
2059 if ( m_xAggregateListBox.is() )
2060 return m_xAggregateListBox->getSelectedItemsPos();
2061 return Sequence< ::sal_Int16 >( );
2064 //--------------------------------------------------------------------
2065 OUString SAL_CALL OListBoxControl::getSelectedItem( ) throw (RuntimeException)
2067 if ( m_xAggregateListBox.is() )
2068 return m_xAggregateListBox->getSelectedItem();
2069 return OUString( );
2072 //--------------------------------------------------------------------
2073 Sequence< OUString > SAL_CALL OListBoxControl::getSelectedItems( ) throw (RuntimeException)
2075 if ( m_xAggregateListBox.is() )
2076 return m_xAggregateListBox->getSelectedItems();
2077 return Sequence< OUString >( );
2080 //--------------------------------------------------------------------
2081 void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException)
2083 if ( m_xAggregateListBox.is() )
2084 m_xAggregateListBox->selectItemPos( nPos, bSelect );
2087 //--------------------------------------------------------------------
2088 void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException)
2090 if ( m_xAggregateListBox.is() )
2091 m_xAggregateListBox->selectItemsPos( aPositions, bSelect );
2094 //--------------------------------------------------------------------
2095 void SAL_CALL OListBoxControl::selectItem( const OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException)
2097 if ( m_xAggregateListBox.is() )
2098 m_xAggregateListBox->selectItem( aItem, bSelect );
2101 //--------------------------------------------------------------------
2102 ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode( ) throw (RuntimeException)
2104 if ( m_xAggregateListBox.is() )
2105 return m_xAggregateListBox->isMutipleMode();
2106 return sal_False;
2109 //--------------------------------------------------------------------
2110 void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException)
2112 if ( m_xAggregateListBox.is() )
2113 m_xAggregateListBox->setMultipleMode( bMulti );
2116 //--------------------------------------------------------------------
2117 ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount( ) throw (RuntimeException)
2119 if ( m_xAggregateListBox.is() )
2120 return m_xAggregateListBox->getDropDownLineCount();
2121 return 0;
2124 //--------------------------------------------------------------------
2125 void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException)
2127 if ( m_xAggregateListBox.is() )
2128 m_xAggregateListBox->setDropDownLineCount( nLines );
2131 //--------------------------------------------------------------------
2132 void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException)
2134 if ( m_xAggregateListBox.is() )
2135 m_xAggregateListBox->makeVisible( nEntry );
2138 //.........................................................................
2140 //.........................................................................
2142 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */